|
51
|
4
|
13
|
2026-05-06T17:31:42.773448+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778088702773_m2.jpg...
|
iTerm2
|
screenpipe"
|
True
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
-rw-r--r-- 1 lukas staff 950993 28 Apr 17:45 -rw-r--r-- 1 lukas staff 950993 28 Apr 17:45 compact_monitor_2_1777387552842.mp4
-rw-r--r-- 1 lukas staff 429007 28 Apr 17:51 compact_monitor_2_1777387889075.mp4
-rw-r--r-- 1 lukas staff 884099 28 Apr 17:57 compact_monitor_2_1777388218623.mp4
-rw-r--r-- 1 lukas staff 2352504 28 Apr 18:02 compact_monitor_2_1777388548021.mp4
-rw-r--r-- 1 lukas staff 3298542 28 Apr 18:07 compact_monitor_2_1777388874095.mp4
-rw-r--r-- 1 lukas staff 2143027 28 Apr 18:13 compact_monitor_2_1777389196097.mp4
-rw-r--r-- 1 lukas staff 2448311 28 Apr 18:18 compact_monitor_2_1777389532297.mp4
-rw-r--r-- 1 lukas staff 2780051 28 Apr 18:24 compact_monitor_2_1777389861076.mp4
-rw-r--r-- 1 lukas staff 2715534 28 Apr 18:29 compact_monitor_2_1777390193677.mp4
-rw-r--r-- 1 lukas staff 2102173 28 Apr 18:35 compact_monitor_2_1777390515997.mp4
-rw-r--r-- 1 lukas staff 2324557 28 Apr 18:40 compact_monitor_2_1777390843577.mp4
-rw-r--r-- 1 lukas staff 1525510 28 Apr 18:46 compact_monitor_2_1777391163945.mp4
-rw-r--r-- 1 lukas staff 2776584 28 Apr 18:51 compact_monitor_2_1777391495138.mp4
-rw-r--r-- 1 lukas staff 1168205 28 Apr 18:57 compact_monitor_2_1777391825305.mp4
-rw-r--r-- 1 lukas staff 1736686 28 Apr 19:02 compact_monitor_2_1777392149583.mp4
-rw-r--r-- 1 lukas staff 2133415 28 Apr 19:07 compact_monitor_2_1777392471754.mp4
-rw-r--r-- 1 lukas staff 1289951 28 Apr 19:13 compact_monitor_2_1777392794343.mp4
-rw-r--r-- 1 lukas staff 223494 28 Apr 19:18 compact_monitor_2_1777393110228.mp4
-rw-r--r-- 1 lukas staff 222168 28 Apr 19:23 compact_monitor_2_1777393424109.mp4
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-04-28 $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22523176
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 28 Apr 16:51 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11525263360 28 Apr 19:33 db.sqlite
-rw-r--r-- 1 lukas staff 65536 28 Apr 15:26 db.sqlite-shm
-rw-r--r-- 1 lukas staff 2323712 28 Apr 22:23 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34227 26 Apr 17:01 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ~/.screenpipe/screenpipe_sync.sh 2026-04-27
[2026-05-06 18:58:18] ========================================
[2026-05-06 18:58:18] Screenpipe sync starting for: 2026-04-27
[2026-05-06 18:58:18] ========================================
[+00m00s] ▶ Preflight checks
Source DB: OK ( 11G)
NAS mount: OK /Volumes/screenpipe
Archive DB: exists (7.7G)
Data dir: OK (242 files, 325M)
[+00m04s] ▶ Counting source rows for 2026-04-27
frames: 7543
elements: 470235
ui_events: 9909
ocr_text: 2193
meetings: 3
[+00m06s] ▶ Initialising tables, indexes, FTS
creating tables ✓ 0m00s
creating indexes ✓ 0m01s
creating FTS tables ✓ 0m00s
[+00m07s] ▶ Syncing data for 2026-04-27
video_chunks ✓ 0m11s
frames (7543 rows) ⠧ Runtime error near line 3: disk I/O error (10)
frames (7543 rows) ⠴ %
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ~/.screenpipe/screenpipe_sync.sh 2026-04-27
[2026-05-06 19:22:16] ========================================
[2026-05-06 19:22:16] Screenpipe sync starting for: 2026-04-27
[2026-05-06 19:22:16] ========================================
[+00m00s] ▶ Preflight checks
Source DB: OK ( 11G)
NAS mount: OK /Volumes/screenpipe
Archive DB: exists (7.7G)
Data dir: OK (242 files, 325M)
[+00m01s] ▶ Counting source rows for 2026-04-27
frames: 7543
elements: 470235
ui_events: 9909
ocr_text: 2193
meetings: 3
[+00m02s] ▶ Initialising tables, indexes, FTS
creating tables ✓ 0m00s
creating indexes ✓ 0m01s
creating FTS tables ✓ 0m00s
[+00m03s] ▶ Syncing data for 2026-04-27
video_chunks ✓ 0m11s
frames (7543 rows) ✓ 4m40s
ocr_text (2193 rows) ✓ 0m25s
ui_events (9909 rows) ✓ 0m02s
elements (470235 rows) ✓ 2m46s
meetings (3 rows) ✓ 0m00s
[+08m07s] ▶ Updating FTS indexes
elements_fts ✓ 2m59s
frames_fts ✓ 6m07s
ui_events_fts ✓ 0m03s
[+17m16s] ▶ Verifying DB
frames: 7543 / 7543 ✓
elements: 470235 / 470235 ✓
ui_events: 9909 / 9909 ✓
ocr_text: 2193 / 2193 ✓
meetings: 3 / 3 ✓
[+18m46s] ▶ Copying data folder for 2026-04-27
rsync 2026-04-27/ → NAS ✓ 0m26s (242 files, 325M)
[2026-05-06 19:41:28] Archive DB size: 9.7G
[2026-05-06 19:41:28] Total time: 19m12s
[2026-05-06 19:41:28] Sync complete for 2026-04-27
[2026-05-06 19:41:28] ========================================
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ~/.screenpipe/screenpipe_sync.sh 2026-04-28
[2026-05-06 19:44:49] ========================================
[2026-05-06 19:44:49] Screenpipe sync starting for: 2026-04-28
[2026-05-06 19:44:49] ========================================
[+00m00s] ▶ Preflight checks
Source DB: OK ( 11G)
NAS mount: OK /Volumes/screenpipe
Archive DB: exists (9.7G)
Data dir: OK (223 files, 159M)
[+00m00s] ▶ Counting source rows for 2026-04-28
frames: 4535
elements: 407532
ui_events: 8621
ocr_text: 1623
meetings: 3
[+00m02s] ▶ Initialising tables, indexes, FTS
creating tables ✓ 0m00s
creating indexes ✓ 0m00s
creating FTS tables ✓ 0m00s
[+00m02s] ▶ Syncing data for 2026-04-28
video_chunks ✓ 0m12s
frames (4535 rows) ✓ 1m30s
ocr_text (1623 rows) ✓ 0m32s
ui_events (8621 rows) ✓ 0m01s
elements (407532 rows) ✓ 1m02s
meetings (3 rows) ✓ 0m00s
[+03m19s] ▶ Updating FTS indexes
elements_fts ✓ 1m36s
frames_fts ✓ 2m28s
ui_events_fts ✓ 0m04s
[+07m27s] ▶ Verifying DB
frames: 4535 / 4535 ✓
elements: 407532 / 407532 ✓
ui_events: 8621 / 8621 ✓
ocr_text: 1623 / 1623 ✓
meetings: 3 / 3 ✓
[+08m59s] ▶ Copying data folder for 2026-04-28
rsync 2026-04-28/ → NAS ✓ 0m20s (223 files, 159M)
[2026-05-06 19:54:08] Archive DB size: 10G
[2026-05-06 19:54:08] Total time: 9m19s
[2026-05-06 19:54:08] Sync complete for 2026-04-28
[2026-05-06 19:54:08] ========================================
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ pkill -f screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ rm -rf ~/.screenpipe/
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 92 lukas staff 2944 6 May 20:22 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd .npm
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ ll
total 24
drwx------ 9 lukas staff 288 28 Apr 09:18 .
drwx------+ 92 lukas staff 2944 6 May 20:22 ..
drwx------ 5 lukas staff 160 1 Nov 2021 _cacache
drwx------@ 2 lukas staff 64 28 Apr 09:18 _locks
drwx------ 15 lukas staff 480 27 Apr 19:54 _logs
drwxr-xr-x 67 lukas staff 2144 28 Apr 09:17 _npx
-rw-r--r--@ 1 lukas staff 0 26 Apr 19:10 _update-notifier-last-checked
-rw-r--r-- 1 lukas staff 173 28 Apr 09:18 anonymous-cli-metrics.json
-rw-r--r-- 1 lukas staff 4764 31 Jan 2024 eresolve-report.txt
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ rm -rf ~/.npm/_npx
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ ll
total 52920
drwx------+ 92 lukas staff 2944 6 May 20:22 .
drwxr-xr-x 5 root admin 160 23 Aug 2024 ..
-r-------- 1 lukas staff 7 18 Nov 2021 .CFUserTextEncoding
-rw-r--r--@ 1 lukas staff 28676 27 Apr 09:11 .DS_Store
drwx------+ 10 lukas staff 320 28 Apr 17:07 .Trash
drwx------ 5 lukas staff 160 1 Nov 2021 .aws
-rw-r--r-- 1 lukas staff 341470 29 Sep 2022 .babel.json
-rw-------@ 1 lukas staff 388 25 Jul 2025 .bash_history
-rw-r--r--@ 1 lukas staff 115 18 Apr 13:19 .bashrc
drwxr-xr-x 5 lukas staff 160 11 Mar 2023 .bito
drwx------@ 6 lukas staff 192 9 Apr 19:53 .cache
drwxr-xr-x 20 lukas staff 640 27 Apr 08:58 .claude
-rw------- 1 lukas staff 28647 27 Apr 09:12 .claude.json
drwxr-xr-x@ 20 lukas staff 640 12 Mar 09:12 .codeium
drwxrwxrwx@ 3 lukas staff 96 2 Mar 2023 .composer
drwx------ 16 lukas staff 512 21 May 2025 .config
drwxr-xr-x 15 lukas staff 480 23 Dec 2024 .continue
drwx------@ 3 lukas staff 96 16 Feb 19:13 .copilot
drwxr-xr-x@ 5 lukas staff 160 9 Apr 2025 .cursor
drwxr-xr-x@ 5 lukas staff 160 17 Aug 2024 .cursor-tutor
drwxr-xr-x 3 lukas staff 96 8 Sep 2024 .daytona
drwxr-xr-x@ 4 lukas staff 128 18 Feb 10:52 .devdb
drwx------ 24 lukas staff 768 27 Apr 18:14 .docker
drwx------ 15 lukas staff 480 6 Jun 2023 .dropbox
drwxr-xr-x@ 3 lukas staff 96 20 Nov 2022 .fig.dotfiles.bak
-rw-r--r-- 1 lukas staff 138 5 Mar 2022 .gauth
-rw-r--r-- 1 lukas staff 220 25 Nov 2021 .gitconfig
-rw-r--r-- 1 lukas staff 12288 25 Nov 2021 .gitconfig.swp
drwx------ 5 lukas staff 160 18 Nov 2021 .hammerspoon
drwxr-xr-x 3 lukas staff 96 21 Mar 2025 .idlerc
-rw------- 1 lukas staff 20 28 Apr 16:51 .lesshst
drwx------ 5 lukas staff 160 23 Dec 2024 .local
-rw------- 1 lukas staff 204 16 Mar 2024 .netrc
drwx------ 3 lukas staff 96 1 Nov 2021 .node-gyp
-rw------- 1 lukas staff 4 6 Feb 2024 .node_repl_history
-rw-r--r-- 1 lukas staff 17 24 Dec 2023 .notion-enhancer
drwxr-xr-x 4 lukas staff 128 12 Jul 2024 .notion-py
drwx------ 8 lukas staff 256 6 May 20:24 .npm
-rw------- 1 lukas staff 74 20 May 2024 .npmrc
drwx------ 32 lukas staff 1024 25 Jul 2025 .nvm
drwxr-xr-x 4 lukas staff 128 5 Aug 2023 .postman
-rw-r--r--@ 1 lukas staff 77 9 Feb 2023 .profile
-rw-------@ 1 lukas staff 3153 21 Mar 2025 .python_history
drwx------ 2 lukas staff 64 15 Nov 2021 .quicktype-vscode
drwxr-xr-x@ 8 lukas staff 256 16 Feb 08:48 .redis-insight
drwxr-xr-x 4 lukas staff 128 4 Feb 09:35 .sonarlint
drwx------ 15 lukas staff 480 8 Aug 2025 .ssh
drwxr-xr-x@ 3 lukas staff 96 15 Aug 2025 .streamlit
drwx------ 6 lukas staff 192 17 Oct 2022 .swiftpm
-rw------- 1 lukas staff 12143 27 Apr 14:58 .viminfo
drwx------ 5 lukas staff 160 19 Jun 2023 .vscode
drwxr-xr-x@ 3 lukas staff 96 20 Jan 2025 .warp
UW PICO 5.09 New Buffer
[ Read 1 line ]
^G Get Help ^O WriteOut ^R Read File ^Y Prev Pg ^K Cut Text ^C Cur Pos
^X Exit ^J Justify ^W Where is ^V Next Pg ^U UnCut Text ^T To Spell
drwxr-xr-x 4 lukas staff 128 29 Apr 2023 .wdm
drwxr-xr-x@ 5 lukas staff 160 26 Jan 13:03 .windsurf
drwxr-xr-x 4 lukas staff 128 24 Mar 12:03 .yarn
-rw-r--r-- 1 lukas staff 116 30 Mar 10:12 .yarnrc
-rw-r--r-- 1 lukas staff 49518 21 Apr 09:09 .zcompdump
-rw-r--r--@ 1 lukas staff 46758 2 Nov 2025 .zcompdump.Lukas-Kovaliks-MacBook-Pro-Jiminny.23381
-rw-r--r--@ 1 lukas staff 6116 20 Apr 19:52 .zprofile
-rw-r--r-- 1 lukas staff 1468 8 Apr 2022 .zprofile-copy
-rw-r--r--@ 1 lukas staff 2900 15 Mar 2023 .zprofile.pysave
-rw------- 1 lukas staff 1731 29 Jun 2022 .zprofile.save
-rw-r--r-- 1 lukas staff 1569 8 Apr 2022 .zprofilees
-rw------- 1 lukas staff 50310 28 Apr 11:32 .zsh_history
drwx------ 9 lukas staff 288 6 May 2025 .zsh_sessions
-rw-r--r--@ 1 lukas staff 400 18 Apr 13:19 .zshrc
drwx------@ 9 lukas staff 288 20 Apr 20:55 Applications
drwxr-xr-x@ 2 lukas staff 64 22 Oct 2025 CascadeProjects
drwxr-xr-x 4 lukas staff 128 27 Oct 2025 DEV
drwx------@ 10 lukas staff 320 28 Apr 18:52 Desktop
drwx------@ 7 lukas staff 224 26 Mar 14:40 Documents
drwx------@ 44 lukas staff 1408 24 Apr 16:53 Downloads
drwxr-xr-x@ 4 lukas staff 128 17 Mar 20:27 Keychron_Screen
drwx------@ 112 lukas staff 3584 2 Dec 09:19 Library
drwx------ 7 lukas staff 224 12 Feb 2024 Movies
drwx------+ 5 lukas staff 160 25 Sep 2023 Music
drwx------+ 9 lukas staff 288 25 Sep 2023 Pictures
drwx------ 3 lukas staff 96 8 Nov 2021 Postman
drwx------+ 4 lukas staff 128 28 Oct 2021 Public
-rw-r--r--@ 1 lukas staff 3950 15 Dec 09:16 Untitled 4.spf
drwx------ 4 lukas staff 128 2 Jul 2023 Users
-rw-r--r-- 1 lukas staff 17050804 27 Apr 19:18 cleanshot-live.log
-rw-r--r-- 1 lukas staff 9363061 27 Apr 19:24 cleanshot-screenpipe.log
-rw-r--r-- 1 lukas staff 0 12 Apr 12:50 clip.mp4
-rw-r--r-- 1 lukas staff 0 12 Apr 12:51 frame.jpg
drwx------ 3 lukas staff 96 30 Sep 2022 iCloud Drive (Archive)
drwx------ 16 lukas staff 512 3 Nov 2025 jiminny
drwxr-xr-x 3 lukas staff 96 20 Mar 18:47 node_modules
drwxr-xr-x 4 lukas staff 128 21 Oct 2025 raycast
-rw-r--r-- 1 lukas staff 0 1 Mar 14:26 response.bin
-rwxr-xr-x 1 lukas staff 3824 11 Apr 15:16 screenpipe-day.sh
-rw-r--r-- 1 lukas staff 86 20 Mar 18:47 yarn.lock
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
cd: no such file or directory: /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ touch screenpipe_sync.sh
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ nano screenpipe_sync.sh
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ npx screenpipe@latest record --ignored-windows "Boosteroid" --retention-days 7
detected hardware tier: Mid
warning: parakeet is not supported on this platform, using whisper-tiny instead
2026-05-06T20:27:32.721416Z INFO screenpipe_engine::auth_key: api auth: key resolved via auto-generated
checking permissions...
screen recording: ok
microphone: ok
accessibility: ok
2026-05-06T20:27:32.831033Z INFO screenpipe_screen::monitor::macos_version: Detected macOS version: 14.6
2026-05-06T20:27:34.088403Z INFO screenpipe_engine::sleep_monitor: Starting macOS sleep/wake monitor
2026-05-06T20:27:34.089942Z INFO screenpipe_engine::sleep_monitor: Screen lock/unlock observers registered (CFNotificationCenter)
2026-05-06T20:27:34.090417Z INFO screenpipe_engine::sleep_monitor: Display reconfiguration watcher registered (CGDisplayRegisterReconfigurationCallback)
2026-05-06T20:27:34.112650Z INFO screenpipe_engine::permission_monitor: permission monitor started screen=true mic=true accessibility=true keychain=true
2026-05-06T20:27:34.112711Z INFO screenpipe: meeting detector enabled — independent of transcription mode
2026-05-06T20:27:34.619906Z INFO screenpipe: API server listening on [IP_ADDRESS]:3030 (localhost only)
2026-05-06T20:27:34.619937Z INFO screenpipe: API auth enabled — run `screenpipe auth token` to view your key
2026-05-06T20:27:34.619857Z INFO screenpipe_engine::snapshot_compaction: snapshot compaction worker started (min_age=600s, poll=300s)
2026-05-06T20:27:34.619847Z INFO screenpipe_engine::power::manager: power manager started (poll interval: 10s)
2026-05-06T20:27:34.620018Z INFO screenpipe_engine::vision_manager::manager: Starting VisionManager
2026-05-06T20:27:34.624746Z INFO screenpipe_core::pipes: installed built-in pipe: day-recap
2026-05-06T20:27:34.626304Z INFO screenpipe_core::pipes: installed built-in pipe: standup-update
2026-05-06T20:27:34.628597Z INFO screenpipe_core::pipes: installed built-in pipe: ai-habits
2026-05-06T20:27:34.629463Z INFO screenpipe_core::pipes: installed built-in pipe: time-breakdown
2026-05-06T20:27:34.630081Z INFO screenpipe_core::pipes: installed built-in pipe: video-export
2026-05-06T20:27:34.630972Z INFO screenpipe_core::pipes: installed built-in pipe: meeting-summary
2026-05-06T20:27:34.631427Z INFO screenpipe_core::pipes: loaded pipe: day-recap
2026-05-06T20:27:34.631521Z INFO screenpipe_core::pipes: loaded pipe: standup-update
2026-05-06T20:27:34.631587Z INFO screenpipe_core::pipes: loaded pipe: ai-habits
2026-05-06T20:27:34.631640Z INFO screenpipe_core::pipes: loaded pipe: time-breakdown
2026-05-06T20:27:34.631690Z INFO screenpipe_core::pipes: loaded pipe: video-export
2026-05-06T20:27:34.631738Z INFO screenpipe_core::pipes: loaded pipe: meeting-summary
2026-05-06T20:27:34.631752Z INFO screenpipe_core::pipes: loaded 6 pipes from "/Users/lukas/.screenpipe/pipes"
_
__________________ ___ ____ ____ (_____ ___
/ ___/ ___/ ___/ _ \/ _ \/ __ \ / __ \/ / __ \/ _ \
(__ / /__/ / / __/ __/ / / / / /_/ / / /_/ / __/
/____/\___/_/ \___/\___/_/ /_/ / .___/_/ .___/\___/
/_/ /_/
power AI by everything you've seen, said or heard
open source | runs locally | developer friendly
┌────────────────────────┬────────────────────────────────────┐
│ setting │ value │
├────────────────────────┼────────────────────────────────────┤
│ audio chunk duration │ 30 seconds │
│ port │ 3030 │
│ audio disabled │ false │
│ vision disabled │ false │
│ pause on DRM content │ false │
│ audio engine │ Parakeet │
│ vad engine │ Silero │
│ data directory │ /Users/lukas/.screenpipe │
│ debug mode │ false │
│ telemetry │ true │
│ use pii removal │ true │
│ use all monitors │ true │
│ ignored windows │ ["Boosteroid"] │
│ included windows │ [] │
│ cloud sync │ disabled │
│ auto-destruct pid │ 0 │
│ deepgram key │ not set │
│ api auth │ enabled │
│ encrypt secrets │ disabled │
│ retention days │ 7 │
│ retention mode │ media-only (keep transcripts) │
├────────────────────────┼────────────────────────────────────┤
│ languages │ │
│ │ all languages │
├────────────────────────┼────────────────────────────────────┤
│ monitors │ │
│ │ id: 1 │
│ │ id: 2 │
├────────────────────────┼────────────────────────────────────┤
│ audio devices │ │
│ │ MacBook Pro Microphone (input) │
│ │ System Audio (output) │
└────────────────────────┴────────────────────────────────────┘
you are using local processing. all your data stays on your computer.
warning: telemetry is enabled. only error-level data will be sent.
to disable, use the --disable-telemetry flag.
check latest changes here: https://github.com/screenpipe/screenpipe/releases
2026-05-06T20:27:34.638384Z INFO screenpipe: starting UI event capture
2026-05-06T20:27:34.637679Z INFO screenpipe_core::pipes: pipe scheduler started (generation 2)
2026-05-06T20:27:34.649154Z INFO screenpipe_engine::power::manager: initial power profile: Performance (on_ac=true, battery=Some(94))
2026-05-06T20:27:34.652794Z WARN screenpipe: pi agent install failed: bun not found — install from https://bun.sh
2026-05-06T20:27:34.655839Z INFO screenpipe_engine::ui_recorder: Starting UI event capture
2026-05-06T20:27:34.673877Z INFO screenpipe_engine::ui_recorder: UI recording session started: 54869993-7b4b-491f-b717-2a583517f9c5
2026-05-06T20:27:34.673910Z INFO screenpipe_engine::calendar_speaker_id: speaker identification: started (user_name=<not set>)
2026-05-06T20:27:34.674057Z INFO screenpipe_engine::hot_frame_cache: hot_frame_cache: warming from DB (2026-05-05 17:27:34.674056 UTC to 2026-05-06 17:27:34.674056 UTC)
2026-05-06T20:27:34.674892Z INFO screenpipe_engine::meeting_detector: meeting v2: detection loop started (base_interval=5s, profiles=12)
2026-05-06T20:27:34.675788Z INFO screenpipe_engine::hot_frame_cache: hot_frame_cache: warmed with 0 frame entries, coverage from 2026-05-05 17:27:34.674056 UTC
2026-05-06T20:27:34.686546Z INFO screenpipe_engine::server: Server listening on [IP_ADDRESS]:3030
2026-05-06T20:27:34.691371Z INFO screenpipe_connect::mdns: mdns: advertising screenpipe on port 3030
2026-05-06T20:27:36.270608Z INFO screenpipe_engine::vision_manager::manager: Starting vision recording for monitor 1 (1440x900)
2026-05-06T20:27:36.270669Z INFO screenpipe_engine::vision_manager::manager: Starting event-driven capture for monitor 1 (device: monitor_1)
2026-05-06T20:27:36.270714Z INFO screenpipe_engine::event_driven_capture: event-driven capture started for monitor 1 (device: monitor_1)
2026-05-06T20:27:36.932583Z INFO screenpipe_engine::vision_manager::manager: Starting vision recording for monitor 2 (3008x1253)
2026-05-06T20:27:36.932852Z INFO screenpipe_engine::vision_manager::manager: Starting event-driven capture for monitor 2 (device: monitor_2)
2026-05-06T20:27:36.932882Z INFO screenpipe_engine::vision_manager::manager: VisionManager started with 2/2 monitor(s)
2026-05-06T20:27:36.932899Z INFO screenpipe_engine::vision_manager::monitor_watcher: Starting monitor watcher (event-driven via CGDisplayRegisterReconfigurationCallback, 60s backstop poll)
2026-05-06T20:27:36.932901Z INFO screenpipe_engine::event_driven_capture: event-driven capture started for monitor 2 (device: monitor_2)
2026-05-06T20:27:39.158281Z INFO sck_rs::stream_manager: persistent SCK stream started for display 1 (1440x900, 2fps, 3 excluded)
2026-05-06T20:27:39.593177Z INFO screenpipe_engine::event_driven_capture: startup capture for monitor 1: frame_id=1, dur=101ms
2026-05-06T20:27:40.672366Z INFO sck_rs::stream_manager: persistent SCK stream started for display 2 (3008x1253, 2fps, 3 excluded)
2026-05-06T20:27:41.257664Z INFO screenpipe_engine::event_driven_capture: startup capture for monitor 2: frame_id=2, dur=140ms
2026-05-06T20:27:44.641022Z INFO screenpipe_audio::transcription::engine: whisper model available: "/Users/lukas/.cache/huggingface/hub/models--ggerganov--whisper.cpp/snapshots/5359861c739e955e79d9a303bcbc70fb988958b1/ggml-tiny.bin"
2026-05-06T20:27:44.641079Z INFO screenpipe_audio::transcription::whisper::model: whisper context: gpu acceleration enabled (Metal on macOS, Vulkan on Windows)
2026-05-06T20:27:44.641086Z INFO screenpipe_audio::transcription::engine: loading whisper model with GPU acceleration...
whisper_init_from_file_with_params_no_state: loading model from '/Users/lukas/.cache/huggingface/hub/models--ggerganov--whisper.cpp/snapshots/5359861c739e955e79d9a303bcbc70fb988958b1/ggml-tiny.bin'
whisper_init_with_params_no_state: use gpu = 1
whisper_init_with_params_no_state: flash attn = 0
whisper_init_with_params_no_state: gpu_device = 0
whisper_init_with_params_no_state: dtw = 0
ggml_metal_device_init: tensor API disabled for pre-M5 and pre-A19 devices
ggml_metal_library_init: using embedded metal library
ggml_metal_library_init: loaded in 0.041 sec
ggml_metal_rsets_init: creating a residency set collection (keep_alive = 180 s)
ggml_metal_device_init: GPU name: Apple M1
ggml_metal_device_init: GPU family: MTLGPUFamilyApple7 (1007)
ggml_metal_device_init: GPU family: MTLGPUFamilyCommon3 (3003)
ggml_metal_device_init: GPU family: MTLGPUFamilyMetal3 (5001)
ggml_metal_device_init: simdgroup reduction = true
ggml_metal_device_init: simdgroup matrix mul. = true
ggml_metal_device_init: has unified memory = true
ggml_metal_device_init: has bfloat = true
ggml_metal_device_init: has tensor = false
ggml_metal_device_init: use residency sets = true
ggml_metal_device_init: use shared buffers = true
ggml_metal_device_init: recommendedMaxWorkingSetSize = 11453.25 MB
whisper_init_with_params_no_state: devices = 3
whisper_init_with_params_no_state: backends = 3
whisper_model_load: loading model
whisper_model_load: n_vocab = 51865
whisper_model_load: n_audio_ctx = 1500
whisper_model_load: n_audio_state = 384
whisper_model_load: n_audio_head = 6
whisper_model_load: n_audio_layer = 4
whisper_model_load: n_text_ctx = 448
whisper_model_load: n_text_state = 384
whisper_model_load: n_text_head = 6
whisper_model_load: n_text_layer = 4
whisper_model_load: n_mels = 80
whisper_model_load: ftype = 1
whisper_model_load: qntvr = 0
whisper_model_load: type = 1 (tiny)
whisper_model_load: adding 1608 extra tokens
whisper_model_load: n_langs = 99
whisper_model_load: Metal total size = 77.11 MB
whisper_model_load: model size = 77.11 MB
2026-05-06T20:27:44.857210Z INFO screenpipe_audio::transcription::engine: whisper model loaded successfully
whisper_backend_init_gpu: device 0: Metal (type: 1)
whisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)
whisper_backend_init_gpu: using Metal backend
ggml_metal_init: allocating
ggml_metal_init: found device: Apple M1
ggml_metal_init: picking default device: Apple M1
ggml_metal_init: use fusion = true
ggml_metal_init: use concurrency = true
ggml_metal_init: use graph optimize = true
whisper_backend_init: using BLAS backend
whisper_init_state: kv self size = 3.15 MB
whisper_init_state: kv cross size = 9.44 MB
whisper_init_state: kv pad size = 2.36 MB
whisper_init_state: compute buffer (conv) = 14.17 MB
whisper_init_state: compute buffer (encode) = 65.96 MB
whisper_init_state: compute buffer (cross) = 8.50 MB
whisper_init_state: compute buffer (decode) = 96.83 MB
2026-05-06T20:27:44.861912Z INFO screenpipe_audio::audio_manager::manager: transcription session created (will be reused across segments)
2026-05-06T20:27:44.862480Z INFO screenpipe_audio::audio_manager::manager: audio manager started
2026-05-06T20:27:44.862525Z INFO screenpipe_audio::audio_manager::manager: calendar-assisted speaker diarization: listening for meeting events
2026-05-06T20:27:47.831980Z INFO screenpipe_audio::device::device_manager: starting recording for device: System Audio (output)
2026-05-06T20:27:47.832191Z INFO screenpipe_audio::core::run_record_and_transcribe: starting continuous recording for System Audio (output) (unknown / 30s segments)
2026-05-06T20:27:47.906029Z INFO screenpipe_audio::device::device_manager: starting recording for device: MacBook Pro Microphone (input)
2026-05-06T20:27:47.906090Z INFO screenpipe_audio::core::run_record_and_transcribe: starting continuous recording for MacBook Pro Microphone (input) (wired / 30s segments)
2026-05-06T20:28:15.251258Z INFO screenpipe_engine::event_driven_capture: content dedup: skipping capture for monitor 1 (hash=-8608554010568040663, trigger=visual_change)
whisper_backend_init_gpu: device 0: Metal (type: 1)
whisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)
whisper_backend_init_gpu: using Metal backend
ggml_metal_init: allocating
ggml_metal_init: found device: Apple M1
ggml_metal_init: picking default device: Apple M1
ggml_metal_init: use fusion = true
ggml_metal_init: use concurrency = true
ggml_metal_init: use graph optimize = true
whisper_backend_init: using BLAS backend
whisper_init_state: kv self size = 3.15 MB
whisper_init_state: kv cross size = 9.44 MB
whisper_init_state: kv pad size = 2.36 MB
whisper_init_state: compute buffer (conv) = 14.17 MB
whisper_init_state: compute buffer (encode) = 65.96 MB
whisper_init_state: compute buffer (cross) = 8.50 MB
whisper_init_state: compute buffer (decode) = 96.83 MB
ggml_metal_free: deallocating
whisper_backend_init_gpu: device 0: Metal (type: 1)
whisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)
whisper_backend_init_gpu: using Metal backend
ggml_metal_init: allocating
ggml_metal_init: found device: Apple M1
ggml_metal_init: picking default device: Apple M1
ggml_metal_init: use fusion = true
ggml_metal_init: use concurrency = true
ggml_metal_init: use graph optimize = true
whisper_backend_init: using BLAS backend
whisper_init_state: kv self size = 3.15 MB
whisper_init_state: kv cross size = 9.44 MB
whisper_init_state: kv pad size = 2.36 MB
whisper_init_state: compute buffer (conv) = 14.17 MB
whisper_init_state: compute buffer (encode) = 65.96 MB
whisper_init_state: compute buffer (cross) = 8.50 MB
whisper_init_state: compute buffer (decode) = 96.83 MB
ggml_metal_free: deallocating
whisper_backend_init_gpu: device 0: Metal (type: 1)
whisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)
whisper_backend_init_gpu: using Metal backend
ggml_metal_init: allocating
ggml_metal_init: found device: Apple M1
ggml_metal_init: picking default device: Apple M1
ggml_metal_init: use fusion = true
ggml_metal_init: use concurrency = true
ggml_metal_init: use graph optimize = true
whisper_backend_init: using BLAS backend
whisper_init_state...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"-rw-r--r-- 1 lukas staff 950993 28 Apr 17:45 compact_monitor_2_1777387552842.mp4\n-rw-r--r-- 1 lukas staff 429007 28 Apr 17:51 compact_monitor_2_1777387889075.mp4\n-rw-r--r-- 1 lukas staff 884099 28 Apr 17:57 compact_monitor_2_1777388218623.mp4\n-rw-r--r-- 1 lukas staff 2352504 28 Apr 18:02 compact_monitor_2_1777388548021.mp4\n-rw-r--r-- 1 lukas staff 3298542 28 Apr 18:07 compact_monitor_2_1777388874095.mp4\n-rw-r--r-- 1 lukas staff 2143027 28 Apr 18:13 compact_monitor_2_1777389196097.mp4\n-rw-r--r-- 1 lukas staff 2448311 28 Apr 18:18 compact_monitor_2_1777389532297.mp4\n-rw-r--r-- 1 lukas staff 2780051 28 Apr 18:24 compact_monitor_2_1777389861076.mp4\n-rw-r--r-- 1 lukas staff 2715534 28 Apr 18:29 compact_monitor_2_1777390193677.mp4\n-rw-r--r-- 1 lukas staff 2102173 28 Apr 18:35 compact_monitor_2_1777390515997.mp4\n-rw-r--r-- 1 lukas staff 2324557 28 Apr 18:40 compact_monitor_2_1777390843577.mp4\n-rw-r--r-- 1 lukas staff 1525510 28 Apr 18:46 compact_monitor_2_1777391163945.mp4\n-rw-r--r-- 1 lukas staff 2776584 28 Apr 18:51 compact_monitor_2_1777391495138.mp4\n-rw-r--r-- 1 lukas staff 1168205 28 Apr 18:57 compact_monitor_2_1777391825305.mp4\n-rw-r--r-- 1 lukas staff 1736686 28 Apr 19:02 compact_monitor_2_1777392149583.mp4\n-rw-r--r-- 1 lukas staff 2133415 28 Apr 19:07 compact_monitor_2_1777392471754.mp4\n-rw-r--r-- 1 lukas staff 1289951 28 Apr 19:13 compact_monitor_2_1777392794343.mp4\n-rw-r--r-- 1 lukas staff 223494 28 Apr 19:18 compact_monitor_2_1777393110228.mp4\n-rw-r--r-- 1 lukas staff 222168 28 Apr 19:23 compact_monitor_2_1777393424109.mp4\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-04-28 $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22523176\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 28 Apr 16:51 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11525263360 28 Apr 19:33 db.sqlite\n-rw-r--r-- 1 lukas staff 65536 28 Apr 15:26 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 2323712 28 Apr 22:23 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34227 26 Apr 17:01 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ~/.screenpipe/screenpipe_sync.sh 2026-04-27 \n[2026-05-06 18:58:18] ========================================\n[2026-05-06 18:58:18] Screenpipe sync starting for: 2026-04-27\n[2026-05-06 18:58:18] ========================================\n\n[+00m00s] ▶ Preflight checks\n Source DB: OK ( 11G)\n NAS mount: OK /Volumes/screenpipe\n Archive DB: exists (7.7G)\n Data dir: OK (242 files, 325M)\n\n[+00m04s] ▶ Counting source rows for 2026-04-27\n frames: 7543\n elements: 470235\n ui_events: 9909\n ocr_text: 2193\n meetings: 3\n\n[+00m06s] ▶ Initialising tables, indexes, FTS\n creating tables ✓ 0m00s\n creating indexes ✓ 0m01s\n creating FTS tables ✓ 0m00s\n\n[+00m07s] ▶ Syncing data for 2026-04-27\n video_chunks ✓ 0m11s\n frames (7543 rows) ⠧ Runtime error near line 3: disk I/O error (10)\n frames (7543 rows) ⠴ % \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ~/.screenpipe/screenpipe_sync.sh 2026-04-27\n[2026-05-06 19:22:16] ========================================\n[2026-05-06 19:22:16] Screenpipe sync starting for: 2026-04-27\n[2026-05-06 19:22:16] ========================================\n\n[+00m00s] ▶ Preflight checks\n Source DB: OK ( 11G)\n NAS mount: OK /Volumes/screenpipe\n Archive DB: exists (7.7G)\n Data dir: OK (242 files, 325M)\n\n[+00m01s] ▶ Counting source rows for 2026-04-27\n frames: 7543\n elements: 470235\n ui_events: 9909\n ocr_text: 2193\n meetings: 3\n\n[+00m02s] ▶ Initialising tables, indexes, FTS\n creating tables ✓ 0m00s\n creating indexes ✓ 0m01s\n creating FTS tables ✓ 0m00s\n\n[+00m03s] ▶ Syncing data for 2026-04-27\n video_chunks ✓ 0m11s\n frames (7543 rows) ✓ 4m40s\n ocr_text (2193 rows) ✓ 0m25s\n ui_events (9909 rows) ✓ 0m02s\n elements (470235 rows) ✓ 2m46s\n meetings (3 rows) ✓ 0m00s\n\n[+08m07s] ▶ Updating FTS indexes\n elements_fts ✓ 2m59s\n frames_fts ✓ 6m07s\n ui_events_fts ✓ 0m03s\n\n[+17m16s] ▶ Verifying DB\n frames: 7543 / 7543 ✓\n elements: 470235 / 470235 ✓\n ui_events: 9909 / 9909 ✓\n ocr_text: 2193 / 2193 ✓\n meetings: 3 / 3 ✓\n\n[+18m46s] ▶ Copying data folder for 2026-04-27\n rsync 2026-04-27/ → NAS ✓ 0m26s (242 files, 325M)\n\n[2026-05-06 19:41:28] Archive DB size: 9.7G\n[2026-05-06 19:41:28] Total time: 19m12s\n[2026-05-06 19:41:28] Sync complete for 2026-04-27\n[2026-05-06 19:41:28] ========================================\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ~/.screenpipe/screenpipe_sync.sh 2026-04-28\n[2026-05-06 19:44:49] ========================================\n[2026-05-06 19:44:49] Screenpipe sync starting for: 2026-04-28\n[2026-05-06 19:44:49] ========================================\n\n[+00m00s] ▶ Preflight checks\n Source DB: OK ( 11G)\n NAS mount: OK /Volumes/screenpipe\n Archive DB: exists (9.7G)\n Data dir: OK (223 files, 159M)\n\n[+00m00s] ▶ Counting source rows for 2026-04-28\n frames: 4535\n elements: 407532\n ui_events: 8621\n ocr_text: 1623\n meetings: 3\n\n[+00m02s] ▶ Initialising tables, indexes, FTS\n creating tables ✓ 0m00s\n creating indexes ✓ 0m00s\n creating FTS tables ✓ 0m00s\n\n[+00m02s] ▶ Syncing data for 2026-04-28\n video_chunks ✓ 0m12s\n frames (4535 rows) ✓ 1m30s\n ocr_text (1623 rows) ✓ 0m32s\n ui_events (8621 rows) ✓ 0m01s\n elements (407532 rows) ✓ 1m02s\n meetings (3 rows) ✓ 0m00s\n\n[+03m19s] ▶ Updating FTS indexes\n elements_fts ✓ 1m36s\n frames_fts ✓ 2m28s\n ui_events_fts ✓ 0m04s\n\n[+07m27s] ▶ Verifying DB\n frames: 4535 / 4535 ✓\n elements: 407532 / 407532 ✓\n ui_events: 8621 / 8621 ✓\n ocr_text: 1623 / 1623 ✓\n meetings: 3 / 3 ✓\n\n[+08m59s] ▶ Copying data folder for 2026-04-28\n rsync 2026-04-28/ → NAS ✓ 0m20s (223 files, 159M)\n\n[2026-05-06 19:54:08] Archive DB size: 10G\n[2026-05-06 19:54:08] Total time: 9m19s\n[2026-05-06 19:54:08] Sync complete for 2026-04-28\n[2026-05-06 19:54:08] ========================================\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ pkill -f screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ rm -rf ~/.screenpipe/\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 92 lukas staff 2944 6 May 20:22 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd .npm \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ ll\ntotal 24\ndrwx------ 9 lukas staff 288 28 Apr 09:18 .\ndrwx------+ 92 lukas staff 2944 6 May 20:22 ..\ndrwx------ 5 lukas staff 160 1 Nov 2021 _cacache\ndrwx------@ 2 lukas staff 64 28 Apr 09:18 _locks\ndrwx------ 15 lukas staff 480 27 Apr 19:54 _logs\ndrwxr-xr-x 67 lukas staff 2144 28 Apr 09:17 _npx\n-rw-r--r--@ 1 lukas staff 0 26 Apr 19:10 _update-notifier-last-checked\n-rw-r--r-- 1 lukas staff 173 28 Apr 09:18 anonymous-cli-metrics.json\n-rw-r--r-- 1 lukas staff 4764 31 Jan 2024 eresolve-report.txt\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ rm -rf ~/.npm/_npx\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ ll \ntotal 52920\ndrwx------+ 92 lukas staff 2944 6 May 20:22 .\ndrwxr-xr-x 5 root admin 160 23 Aug 2024 ..\n-r-------- 1 lukas staff 7 18 Nov 2021 .CFUserTextEncoding\n-rw-r--r--@ 1 lukas staff 28676 27 Apr 09:11 .DS_Store\ndrwx------+ 10 lukas staff 320 28 Apr 17:07 .Trash\ndrwx------ 5 lukas staff 160 1 Nov 2021 .aws\n-rw-r--r-- 1 lukas staff 341470 29 Sep 2022 .babel.json\n-rw-------@ 1 lukas staff 388 25 Jul 2025 .bash_history\n-rw-r--r--@ 1 lukas staff 115 18 Apr 13:19 .bashrc\ndrwxr-xr-x 5 lukas staff 160 11 Mar 2023 .bito\ndrwx------@ 6 lukas staff 192 9 Apr 19:53 .cache\ndrwxr-xr-x 20 lukas staff 640 27 Apr 08:58 .claude\n-rw------- 1 lukas staff 28647 27 Apr 09:12 .claude.json\ndrwxr-xr-x@ 20 lukas staff 640 12 Mar 09:12 .codeium\ndrwxrwxrwx@ 3 lukas staff 96 2 Mar 2023 .composer\ndrwx------ 16 lukas staff 512 21 May 2025 .config\ndrwxr-xr-x 15 lukas staff 480 23 Dec 2024 .continue\ndrwx------@ 3 lukas staff 96 16 Feb 19:13 .copilot\ndrwxr-xr-x@ 5 lukas staff 160 9 Apr 2025 .cursor\ndrwxr-xr-x@ 5 lukas staff 160 17 Aug 2024 .cursor-tutor\ndrwxr-xr-x 3 lukas staff 96 8 Sep 2024 .daytona\ndrwxr-xr-x@ 4 lukas staff 128 18 Feb 10:52 .devdb\ndrwx------ 24 lukas staff 768 27 Apr 18:14 .docker\ndrwx------ 15 lukas staff 480 6 Jun 2023 .dropbox\ndrwxr-xr-x@ 3 lukas staff 96 20 Nov 2022 .fig.dotfiles.bak\n-rw-r--r-- 1 lukas staff 138 5 Mar 2022 .gauth\n-rw-r--r-- 1 lukas staff 220 25 Nov 2021 .gitconfig\n-rw-r--r-- 1 lukas staff 12288 25 Nov 2021 .gitconfig.swp\ndrwx------ 5 lukas staff 160 18 Nov 2021 .hammerspoon\ndrwxr-xr-x 3 lukas staff 96 21 Mar 2025 .idlerc\n-rw------- 1 lukas staff 20 28 Apr 16:51 .lesshst\ndrwx------ 5 lukas staff 160 23 Dec 2024 .local\n-rw------- 1 lukas staff 204 16 Mar 2024 .netrc\ndrwx------ 3 lukas staff 96 1 Nov 2021 .node-gyp\n-rw------- 1 lukas staff 4 6 Feb 2024 .node_repl_history\n-rw-r--r-- 1 lukas staff 17 24 Dec 2023 .notion-enhancer\ndrwxr-xr-x 4 lukas staff 128 12 Jul 2024 .notion-py\ndrwx------ 8 lukas staff 256 6 May 20:24 .npm\n-rw------- 1 lukas staff 74 20 May 2024 .npmrc\ndrwx------ 32 lukas staff 1024 25 Jul 2025 .nvm\ndrwxr-xr-x 4 lukas staff 128 5 Aug 2023 .postman\n-rw-r--r--@ 1 lukas staff 77 9 Feb 2023 .profile\n-rw-------@ 1 lukas staff 3153 21 Mar 2025 .python_history\ndrwx------ 2 lukas staff 64 15 Nov 2021 .quicktype-vscode\ndrwxr-xr-x@ 8 lukas staff 256 16 Feb 08:48 .redis-insight\ndrwxr-xr-x 4 lukas staff 128 4 Feb 09:35 .sonarlint\ndrwx------ 15 lukas staff 480 8 Aug 2025 .ssh\ndrwxr-xr-x@ 3 lukas staff 96 15 Aug 2025 .streamlit\ndrwx------ 6 lukas staff 192 17 Oct 2022 .swiftpm\n-rw------- 1 lukas staff 12143 27 Apr 14:58 .viminfo\ndrwx------ 5 lukas staff 160 19 Jun 2023 .vscode\ndrwxr-xr-x@ 3 lukas staff 96 20 Jan 2025 .warp\n UW PICO 5.09 New Buffer \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n [ Read 1 line ] \n^G Get Help ^O WriteOut ^R Read File ^Y Prev Pg ^K Cut Text ^C Cur Pos \n^X Exit ^J Justify ^W Where is ^V Next Pg ^U UnCut Text ^T To Spell \ndrwxr-xr-x 4 lukas staff 128 29 Apr 2023 .wdm\ndrwxr-xr-x@ 5 lukas staff 160 26 Jan 13:03 .windsurf\ndrwxr-xr-x 4 lukas staff 128 24 Mar 12:03 .yarn\n-rw-r--r-- 1 lukas staff 116 30 Mar 10:12 .yarnrc\n-rw-r--r-- 1 lukas staff 49518 21 Apr 09:09 .zcompdump\n-rw-r--r--@ 1 lukas staff 46758 2 Nov 2025 .zcompdump.Lukas-Kovaliks-MacBook-Pro-Jiminny.23381\n-rw-r--r--@ 1 lukas staff 6116 20 Apr 19:52 .zprofile\n-rw-r--r-- 1 lukas staff 1468 8 Apr 2022 .zprofile-copy\n-rw-r--r--@ 1 lukas staff 2900 15 Mar 2023 .zprofile.pysave\n-rw------- 1 lukas staff 1731 29 Jun 2022 .zprofile.save\n-rw-r--r-- 1 lukas staff 1569 8 Apr 2022 .zprofilees\n-rw------- 1 lukas staff 50310 28 Apr 11:32 .zsh_history\ndrwx------ 9 lukas staff 288 6 May 2025 .zsh_sessions\n-rw-r--r--@ 1 lukas staff 400 18 Apr 13:19 .zshrc\ndrwx------@ 9 lukas staff 288 20 Apr 20:55 Applications\ndrwxr-xr-x@ 2 lukas staff 64 22 Oct 2025 CascadeProjects\ndrwxr-xr-x 4 lukas staff 128 27 Oct 2025 DEV\ndrwx------@ 10 lukas staff 320 28 Apr 18:52 Desktop\ndrwx------@ 7 lukas staff 224 26 Mar 14:40 Documents\ndrwx------@ 44 lukas staff 1408 24 Apr 16:53 Downloads\ndrwxr-xr-x@ 4 lukas staff 128 17 Mar 20:27 Keychron_Screen\ndrwx------@ 112 lukas staff 3584 2 Dec 09:19 Library\ndrwx------ 7 lukas staff 224 12 Feb 2024 Movies\ndrwx------+ 5 lukas staff 160 25 Sep 2023 Music\ndrwx------+ 9 lukas staff 288 25 Sep 2023 Pictures\ndrwx------ 3 lukas staff 96 8 Nov 2021 Postman\ndrwx------+ 4 lukas staff 128 28 Oct 2021 Public\n-rw-r--r--@ 1 lukas staff 3950 15 Dec 09:16 Untitled 4.spf\ndrwx------ 4 lukas staff 128 2 Jul 2023 Users\n-rw-r--r-- 1 lukas staff 17050804 27 Apr 19:18 cleanshot-live.log\n-rw-r--r-- 1 lukas staff 9363061 27 Apr 19:24 cleanshot-screenpipe.log\n-rw-r--r-- 1 lukas staff 0 12 Apr 12:50 clip.mp4\n-rw-r--r-- 1 lukas staff 0 12 Apr 12:51 frame.jpg\ndrwx------ 3 lukas staff 96 30 Sep 2022 iCloud Drive (Archive)\ndrwx------ 16 lukas staff 512 3 Nov 2025 jiminny\ndrwxr-xr-x 3 lukas staff 96 20 Mar 18:47 node_modules\ndrwxr-xr-x 4 lukas staff 128 21 Oct 2025 raycast\n-rw-r--r-- 1 lukas staff 0 1 Mar 14:26 response.bin\n-rwxr-xr-x 1 lukas staff 3824 11 Apr 15:16 screenpipe-day.sh\n-rw-r--r-- 1 lukas staff 86 20 Mar 18:47 yarn.lock\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe\ncd: no such file or directory: /Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ touch screenpipe_sync.sh\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ nano screenpipe_sync.sh\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ npx screenpipe@latest record --ignored-windows \"Boosteroid\" --retention-days 7\ndetected hardware tier: Mid\nwarning: parakeet is not supported on this platform, using whisper-tiny instead\n2026-05-06T20:27:32.721416Z INFO screenpipe_engine::auth_key: api auth: key resolved via auto-generated\nchecking permissions...\n screen recording: ok\n microphone: ok\n accessibility: ok\n2026-05-06T20:27:32.831033Z INFO screenpipe_screen::monitor::macos_version: Detected macOS version: 14.6\n2026-05-06T20:27:34.088403Z INFO screenpipe_engine::sleep_monitor: Starting macOS sleep/wake monitor\n2026-05-06T20:27:34.089942Z INFO screenpipe_engine::sleep_monitor: Screen lock/unlock observers registered (CFNotificationCenter)\n2026-05-06T20:27:34.090417Z INFO screenpipe_engine::sleep_monitor: Display reconfiguration watcher registered (CGDisplayRegisterReconfigurationCallback)\n2026-05-06T20:27:34.112650Z INFO screenpipe_engine::permission_monitor: permission monitor started screen=true mic=true accessibility=true keychain=true\n2026-05-06T20:27:34.112711Z INFO screenpipe: meeting detector enabled — independent of transcription mode\n2026-05-06T20:27:34.619906Z INFO screenpipe: API server listening on 127.0.0.1:3030 (localhost only)\n2026-05-06T20:27:34.619937Z INFO screenpipe: API auth enabled — run `screenpipe auth token` to view your key\n2026-05-06T20:27:34.619857Z INFO screenpipe_engine::snapshot_compaction: snapshot compaction worker started (min_age=600s, poll=300s)\n2026-05-06T20:27:34.619847Z INFO screenpipe_engine::power::manager: power manager started (poll interval: 10s)\n2026-05-06T20:27:34.620018Z INFO screenpipe_engine::vision_manager::manager: Starting VisionManager\n2026-05-06T20:27:34.624746Z INFO screenpipe_core::pipes: installed built-in pipe: day-recap\n2026-05-06T20:27:34.626304Z INFO screenpipe_core::pipes: installed built-in pipe: standup-update\n2026-05-06T20:27:34.628597Z INFO screenpipe_core::pipes: installed built-in pipe: ai-habits\n2026-05-06T20:27:34.629463Z INFO screenpipe_core::pipes: installed built-in pipe: time-breakdown\n2026-05-06T20:27:34.630081Z INFO screenpipe_core::pipes: installed built-in pipe: video-export\n2026-05-06T20:27:34.630972Z INFO screenpipe_core::pipes: installed built-in pipe: meeting-summary\n2026-05-06T20:27:34.631427Z INFO screenpipe_core::pipes: loaded pipe: day-recap\n2026-05-06T20:27:34.631521Z INFO screenpipe_core::pipes: loaded pipe: standup-update\n2026-05-06T20:27:34.631587Z INFO screenpipe_core::pipes: loaded pipe: ai-habits\n2026-05-06T20:27:34.631640Z INFO screenpipe_core::pipes: loaded pipe: time-breakdown\n2026-05-06T20:27:34.631690Z INFO screenpipe_core::pipes: loaded pipe: video-export\n2026-05-06T20:27:34.631738Z INFO screenpipe_core::pipes: loaded pipe: meeting-summary\n2026-05-06T20:27:34.631752Z INFO screenpipe_core::pipes: loaded 6 pipes from \"/Users/lukas/.screenpipe/pipes\"\n\n\n\n _ \n __________________ ___ ____ ____ (_____ ___ \n / ___/ ___/ ___/ _ \\/ _ \\/ __ \\ / __ \\/ / __ \\/ _ \\\n (__ / /__/ / / __/ __/ / / / / /_/ / / /_/ / __/\n/____/\\___/_/ \\___/\\___/_/ /_/ / .___/_/ .___/\\___/ \n /_/ /_/ \n\n\n\npower AI by everything you've seen, said or heard\nopen source | runs locally | developer friendly\n\n\n┌────────────────────────┬────────────────────────────────────┐\n│ setting │ value │\n├────────────────────────┼────────────────────────────────────┤\n│ audio chunk duration │ 30 seconds │\n│ port │ 3030 │\n│ audio disabled │ false │\n│ vision disabled │ false │\n│ pause on DRM content │ false │\n│ audio engine │ Parakeet │\n│ vad engine │ Silero │\n│ data directory │ /Users/lukas/.screenpipe │\n│ debug mode │ false │\n│ telemetry │ true │\n│ use pii removal │ true │\n│ use all monitors │ true │\n│ ignored windows │ [\"Boosteroid\"] │\n│ included windows │ [] │\n│ cloud sync │ disabled │\n│ auto-destruct pid │ 0 │\n│ deepgram key │ not set │\n│ api auth │ enabled │\n│ encrypt secrets │ disabled │\n│ retention days │ 7 │\n│ retention mode │ media-only (keep transcripts) │\n├────────────────────────┼────────────────────────────────────┤\n│ languages │ │\n│ │ all languages │\n├────────────────────────┼────────────────────────────────────┤\n│ monitors │ │\n│ │ id: 1 │\n│ │ id: 2 │\n├────────────────────────┼────────────────────────────────────┤\n│ audio devices │ │\n│ │ MacBook Pro Microphone (input) │\n│ │ System Audio (output) │\n└────────────────────────┴────────────────────────────────────┘\nyou are using local processing. all your data stays on your computer.\n\nwarning: telemetry is enabled. only error-level data will be sent.\nto disable, use the --disable-telemetry flag.\n\ncheck latest changes here: https://github.com/screenpipe/screenpipe/releases\n2026-05-06T20:27:34.638384Z INFO screenpipe: starting UI event capture\n2026-05-06T20:27:34.637679Z INFO screenpipe_core::pipes: pipe scheduler started (generation 2)\n2026-05-06T20:27:34.649154Z INFO screenpipe_engine::power::manager: initial power profile: Performance (on_ac=true, battery=Some(94))\n2026-05-06T20:27:34.652794Z WARN screenpipe: pi agent install failed: bun not found — install from https://bun.sh\n2026-05-06T20:27:34.655839Z INFO screenpipe_engine::ui_recorder: Starting UI event capture\n2026-05-06T20:27:34.673877Z INFO screenpipe_engine::ui_recorder: UI recording session started: 54869993-7b4b-491f-b717-2a583517f9c5\n2026-05-06T20:27:34.673910Z INFO screenpipe_engine::calendar_speaker_id: speaker identification: started (user_name=<not set>)\n2026-05-06T20:27:34.674057Z INFO screenpipe_engine::hot_frame_cache: hot_frame_cache: warming from DB (2026-05-05 17:27:34.674056 UTC to 2026-05-06 17:27:34.674056 UTC)\n2026-05-06T20:27:34.674892Z INFO screenpipe_engine::meeting_detector: meeting v2: detection loop started (base_interval=5s, profiles=12)\n2026-05-06T20:27:34.675788Z INFO screenpipe_engine::hot_frame_cache: hot_frame_cache: warmed with 0 frame entries, coverage from 2026-05-05 17:27:34.674056 UTC\n2026-05-06T20:27:34.686546Z INFO screenpipe_engine::server: Server listening on 127.0.0.1:3030\n2026-05-06T20:27:34.691371Z INFO screenpipe_connect::mdns: mdns: advertising screenpipe on port 3030\n2026-05-06T20:27:36.270608Z INFO screenpipe_engine::vision_manager::manager: Starting vision recording for monitor 1 (1440x900)\n2026-05-06T20:27:36.270669Z INFO screenpipe_engine::vision_manager::manager: Starting event-driven capture for monitor 1 (device: monitor_1)\n2026-05-06T20:27:36.270714Z INFO screenpipe_engine::event_driven_capture: event-driven capture started for monitor 1 (device: monitor_1)\n2026-05-06T20:27:36.932583Z INFO screenpipe_engine::vision_manager::manager: Starting vision recording for monitor 2 (3008x1253)\n2026-05-06T20:27:36.932852Z INFO screenpipe_engine::vision_manager::manager: Starting event-driven capture for monitor 2 (device: monitor_2)\n2026-05-06T20:27:36.932882Z INFO screenpipe_engine::vision_manager::manager: VisionManager started with 2/2 monitor(s)\n2026-05-06T20:27:36.932899Z INFO screenpipe_engine::vision_manager::monitor_watcher: Starting monitor watcher (event-driven via CGDisplayRegisterReconfigurationCallback, 60s backstop poll)\n2026-05-06T20:27:36.932901Z INFO screenpipe_engine::event_driven_capture: event-driven capture started for monitor 2 (device: monitor_2)\n2026-05-06T20:27:39.158281Z INFO sck_rs::stream_manager: persistent SCK stream started for display 1 (1440x900, 2fps, 3 excluded)\n2026-05-06T20:27:39.593177Z INFO screenpipe_engine::event_driven_capture: startup capture for monitor 1: frame_id=1, dur=101ms\n2026-05-06T20:27:40.672366Z INFO sck_rs::stream_manager: persistent SCK stream started for display 2 (3008x1253, 2fps, 3 excluded)\n2026-05-06T20:27:41.257664Z INFO screenpipe_engine::event_driven_capture: startup capture for monitor 2: frame_id=2, dur=140ms\n2026-05-06T20:27:44.641022Z INFO screenpipe_audio::transcription::engine: whisper model available: \"/Users/lukas/.cache/huggingface/hub/models--ggerganov--whisper.cpp/snapshots/5359861c739e955e79d9a303bcbc70fb988958b1/ggml-tiny.bin\"\n2026-05-06T20:27:44.641079Z INFO screenpipe_audio::transcription::whisper::model: whisper context: gpu acceleration enabled (Metal on macOS, Vulkan on Windows)\n2026-05-06T20:27:44.641086Z INFO screenpipe_audio::transcription::engine: loading whisper model with GPU acceleration...\nwhisper_init_from_file_with_params_no_state: loading model from '/Users/lukas/.cache/huggingface/hub/models--ggerganov--whisper.cpp/snapshots/5359861c739e955e79d9a303bcbc70fb988958b1/ggml-tiny.bin'\nwhisper_init_with_params_no_state: use gpu = 1\nwhisper_init_with_params_no_state: flash attn = 0\nwhisper_init_with_params_no_state: gpu_device = 0\nwhisper_init_with_params_no_state: dtw = 0\nggml_metal_device_init: tensor API disabled for pre-M5 and pre-A19 devices\nggml_metal_library_init: using embedded metal library\nggml_metal_library_init: loaded in 0.041 sec\nggml_metal_rsets_init: creating a residency set collection (keep_alive = 180 s)\nggml_metal_device_init: GPU name: Apple M1\nggml_metal_device_init: GPU family: MTLGPUFamilyApple7 (1007)\nggml_metal_device_init: GPU family: MTLGPUFamilyCommon3 (3003)\nggml_metal_device_init: GPU family: MTLGPUFamilyMetal3 (5001)\nggml_metal_device_init: simdgroup reduction = true\nggml_metal_device_init: simdgroup matrix mul. = true\nggml_metal_device_init: has unified memory = true\nggml_metal_device_init: has bfloat = true\nggml_metal_device_init: has tensor = false\nggml_metal_device_init: use residency sets = true\nggml_metal_device_init: use shared buffers = true\nggml_metal_device_init: recommendedMaxWorkingSetSize = 11453.25 MB\nwhisper_init_with_params_no_state: devices = 3\nwhisper_init_with_params_no_state: backends = 3\nwhisper_model_load: loading model\nwhisper_model_load: n_vocab = 51865\nwhisper_model_load: n_audio_ctx = 1500\nwhisper_model_load: n_audio_state = 384\nwhisper_model_load: n_audio_head = 6\nwhisper_model_load: n_audio_layer = 4\nwhisper_model_load: n_text_ctx = 448\nwhisper_model_load: n_text_state = 384\nwhisper_model_load: n_text_head = 6\nwhisper_model_load: n_text_layer = 4\nwhisper_model_load: n_mels = 80\nwhisper_model_load: ftype = 1\nwhisper_model_load: qntvr = 0\nwhisper_model_load: type = 1 (tiny)\nwhisper_model_load: adding 1608 extra tokens\nwhisper_model_load: n_langs = 99\nwhisper_model_load: Metal total size = 77.11 MB\nwhisper_model_load: model size = 77.11 MB\n2026-05-06T20:27:44.857210Z INFO screenpipe_audio::transcription::engine: whisper model loaded successfully\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\n2026-05-06T20:27:44.861912Z INFO screenpipe_audio::audio_manager::manager: transcription session created (will be reused across segments)\n2026-05-06T20:27:44.862480Z INFO screenpipe_audio::audio_manager::manager: audio manager started\n2026-05-06T20:27:44.862525Z INFO screenpipe_audio::audio_manager::manager: calendar-assisted speaker diarization: listening for meeting events\n2026-05-06T20:27:47.831980Z INFO screenpipe_audio::device::device_manager: starting recording for device: System Audio (output)\n2026-05-06T20:27:47.832191Z INFO screenpipe_audio::core::run_record_and_transcribe: starting continuous recording for System Audio (output) (unknown / 30s segments)\n2026-05-06T20:27:47.906029Z INFO screenpipe_audio::device::device_manager: starting recording for device: MacBook Pro Microphone (input)\n2026-05-06T20:27:47.906090Z INFO screenpipe_audio::core::run_record_and_transcribe: starting continuous recording for MacBook Pro Microphone (input) (wired / 30s segments)\n2026-05-06T20:28:15.251258Z INFO screenpipe_engine::event_driven_capture: content dedup: skipping capture for monitor 1 (hash=-8608554010568040663, trigger=visual_change)\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\n2026-05-06T20:29:45.187551Z INFO screenpipe_audio::audio_manager::manager: reconciliation: transcribed 6 orphaned chunks\n2026-05-06T20:30:06.916244Z WARN screenpipe_audio::core::source_buffer: [MacBook Pro Microphone (input)] large gap on wired device: 81.4ms elapsed (expected 5.3ms) → inserting 76.0ms silence (7299 samples)\n2026-05-06T20:30:29.881247Z WARN screenpipe_audio::core::source_buffer: [MacBook Pro Microphone (input)] large gap on wired device: 96.0ms elapsed (expected 5.3ms) → inserting 90.7ms silence (8704 samples)","depth":4,"on_screen":true,"value":"-rw-r--r-- 1 lukas staff 950993 28 Apr 17:45 compact_monitor_2_1777387552842.mp4\n-rw-r--r-- 1 lukas staff 429007 28 Apr 17:51 compact_monitor_2_1777387889075.mp4\n-rw-r--r-- 1 lukas staff 884099 28 Apr 17:57 compact_monitor_2_1777388218623.mp4\n-rw-r--r-- 1 lukas staff 2352504 28 Apr 18:02 compact_monitor_2_1777388548021.mp4\n-rw-r--r-- 1 lukas staff 3298542 28 Apr 18:07 compact_monitor_2_1777388874095.mp4\n-rw-r--r-- 1 lukas staff 2143027 28 Apr 18:13 compact_monitor_2_1777389196097.mp4\n-rw-r--r-- 1 lukas staff 2448311 28 Apr 18:18 compact_monitor_2_1777389532297.mp4\n-rw-r--r-- 1 lukas staff 2780051 28 Apr 18:24 compact_monitor_2_1777389861076.mp4\n-rw-r--r-- 1 lukas staff 2715534 28 Apr 18:29 compact_monitor_2_1777390193677.mp4\n-rw-r--r-- 1 lukas staff 2102173 28 Apr 18:35 compact_monitor_2_1777390515997.mp4\n-rw-r--r-- 1 lukas staff 2324557 28 Apr 18:40 compact_monitor_2_1777390843577.mp4\n-rw-r--r-- 1 lukas staff 1525510 28 Apr 18:46 compact_monitor_2_1777391163945.mp4\n-rw-r--r-- 1 lukas staff 2776584 28 Apr 18:51 compact_monitor_2_1777391495138.mp4\n-rw-r--r-- 1 lukas staff 1168205 28 Apr 18:57 compact_monitor_2_1777391825305.mp4\n-rw-r--r-- 1 lukas staff 1736686 28 Apr 19:02 compact_monitor_2_1777392149583.mp4\n-rw-r--r-- 1 lukas staff 2133415 28 Apr 19:07 compact_monitor_2_1777392471754.mp4\n-rw-r--r-- 1 lukas staff 1289951 28 Apr 19:13 compact_monitor_2_1777392794343.mp4\n-rw-r--r-- 1 lukas staff 223494 28 Apr 19:18 compact_monitor_2_1777393110228.mp4\n-rw-r--r-- 1 lukas staff 222168 28 Apr 19:23 compact_monitor_2_1777393424109.mp4\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-04-28 $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22523176\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 28 Apr 16:51 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11525263360 28 Apr 19:33 db.sqlite\n-rw-r--r-- 1 lukas staff 65536 28 Apr 15:26 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 2323712 28 Apr 22:23 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34227 26 Apr 17:01 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ~/.screenpipe/screenpipe_sync.sh 2026-04-27 \n[2026-05-06 18:58:18] ========================================\n[2026-05-06 18:58:18] Screenpipe sync starting for: 2026-04-27\n[2026-05-06 18:58:18] ========================================\n\n[+00m00s] ▶ Preflight checks\n Source DB: OK ( 11G)\n NAS mount: OK /Volumes/screenpipe\n Archive DB: exists (7.7G)\n Data dir: OK (242 files, 325M)\n\n[+00m04s] ▶ Counting source rows for 2026-04-27\n frames: 7543\n elements: 470235\n ui_events: 9909\n ocr_text: 2193\n meetings: 3\n\n[+00m06s] ▶ Initialising tables, indexes, FTS\n creating tables ✓ 0m00s\n creating indexes ✓ 0m01s\n creating FTS tables ✓ 0m00s\n\n[+00m07s] ▶ Syncing data for 2026-04-27\n video_chunks ✓ 0m11s\n frames (7543 rows) ⠧ Runtime error near line 3: disk I/O error (10)\n frames (7543 rows) ⠴ % \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ~/.screenpipe/screenpipe_sync.sh 2026-04-27\n[2026-05-06 19:22:16] ========================================\n[2026-05-06 19:22:16] Screenpipe sync starting for: 2026-04-27\n[2026-05-06 19:22:16] ========================================\n\n[+00m00s] ▶ Preflight checks\n Source DB: OK ( 11G)\n NAS mount: OK /Volumes/screenpipe\n Archive DB: exists (7.7G)\n Data dir: OK (242 files, 325M)\n\n[+00m01s] ▶ Counting source rows for 2026-04-27\n frames: 7543\n elements: 470235\n ui_events: 9909\n ocr_text: 2193\n meetings: 3\n\n[+00m02s] ▶ Initialising tables, indexes, FTS\n creating tables ✓ 0m00s\n creating indexes ✓ 0m01s\n creating FTS tables ✓ 0m00s\n\n[+00m03s] ▶ Syncing data for 2026-04-27\n video_chunks ✓ 0m11s\n frames (7543 rows) ✓ 4m40s\n ocr_text (2193 rows) ✓ 0m25s\n ui_events (9909 rows) ✓ 0m02s\n elements (470235 rows) ✓ 2m46s\n meetings (3 rows) ✓ 0m00s\n\n[+08m07s] ▶ Updating FTS indexes\n elements_fts ✓ 2m59s\n frames_fts ✓ 6m07s\n ui_events_fts ✓ 0m03s\n\n[+17m16s] ▶ Verifying DB\n frames: 7543 / 7543 ✓\n elements: 470235 / 470235 ✓\n ui_events: 9909 / 9909 ✓\n ocr_text: 2193 / 2193 ✓\n meetings: 3 / 3 ✓\n\n[+18m46s] ▶ Copying data folder for 2026-04-27\n rsync 2026-04-27/ → NAS ✓ 0m26s (242 files, 325M)\n\n[2026-05-06 19:41:28] Archive DB size: 9.7G\n[2026-05-06 19:41:28] Total time: 19m12s\n[2026-05-06 19:41:28] Sync complete for 2026-04-27\n[2026-05-06 19:41:28] ========================================\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ~/.screenpipe/screenpipe_sync.sh 2026-04-28\n[2026-05-06 19:44:49] ========================================\n[2026-05-06 19:44:49] Screenpipe sync starting for: 2026-04-28\n[2026-05-06 19:44:49] ========================================\n\n[+00m00s] ▶ Preflight checks\n Source DB: OK ( 11G)\n NAS mount: OK /Volumes/screenpipe\n Archive DB: exists (9.7G)\n Data dir: OK (223 files, 159M)\n\n[+00m00s] ▶ Counting source rows for 2026-04-28\n frames: 4535\n elements: 407532\n ui_events: 8621\n ocr_text: 1623\n meetings: 3\n\n[+00m02s] ▶ Initialising tables, indexes, FTS\n creating tables ✓ 0m00s\n creating indexes ✓ 0m00s\n creating FTS tables ✓ 0m00s\n\n[+00m02s] ▶ Syncing data for 2026-04-28\n video_chunks ✓ 0m12s\n frames (4535 rows) ✓ 1m30s\n ocr_text (1623 rows) ✓ 0m32s\n ui_events (8621 rows) ✓ 0m01s\n elements (407532 rows) ✓ 1m02s\n meetings (3 rows) ✓ 0m00s\n\n[+03m19s] ▶ Updating FTS indexes\n elements_fts ✓ 1m36s\n frames_fts ✓ 2m28s\n ui_events_fts ✓ 0m04s\n\n[+07m27s] ▶ Verifying DB\n frames: 4535 / 4535 ✓\n elements: 407532 / 407532 ✓\n ui_events: 8621 / 8621 ✓\n ocr_text: 1623 / 1623 ✓\n meetings: 3 / 3 ✓\n\n[+08m59s] ▶ Copying data folder for 2026-04-28\n rsync 2026-04-28/ → NAS ✓ 0m20s (223 files, 159M)\n\n[2026-05-06 19:54:08] Archive DB size: 10G\n[2026-05-06 19:54:08] Total time: 9m19s\n[2026-05-06 19:54:08] Sync complete for 2026-04-28\n[2026-05-06 19:54:08] ========================================\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ pkill -f screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ rm -rf ~/.screenpipe/\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 92 lukas staff 2944 6 May 20:22 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd .npm \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ ll\ntotal 24\ndrwx------ 9 lukas staff 288 28 Apr 09:18 .\ndrwx------+ 92 lukas staff 2944 6 May 20:22 ..\ndrwx------ 5 lukas staff 160 1 Nov 2021 _cacache\ndrwx------@ 2 lukas staff 64 28 Apr 09:18 _locks\ndrwx------ 15 lukas staff 480 27 Apr 19:54 _logs\ndrwxr-xr-x 67 lukas staff 2144 28 Apr 09:17 _npx\n-rw-r--r--@ 1 lukas staff 0 26 Apr 19:10 _update-notifier-last-checked\n-rw-r--r-- 1 lukas staff 173 28 Apr 09:18 anonymous-cli-metrics.json\n-rw-r--r-- 1 lukas staff 4764 31 Jan 2024 eresolve-report.txt\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ rm -rf ~/.npm/_npx\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ ll \ntotal 52920\ndrwx------+ 92 lukas staff 2944 6 May 20:22 .\ndrwxr-xr-x 5 root admin 160 23 Aug 2024 ..\n-r-------- 1 lukas staff 7 18 Nov 2021 .CFUserTextEncoding\n-rw-r--r--@ 1 lukas staff 28676 27 Apr 09:11 .DS_Store\ndrwx------+ 10 lukas staff 320 28 Apr 17:07 .Trash\ndrwx------ 5 lukas staff 160 1 Nov 2021 .aws\n-rw-r--r-- 1 lukas staff 341470 29 Sep 2022 .babel.json\n-rw-------@ 1 lukas staff 388 25 Jul 2025 .bash_history\n-rw-r--r--@ 1 lukas staff 115 18 Apr 13:19 .bashrc\ndrwxr-xr-x 5 lukas staff 160 11 Mar 2023 .bito\ndrwx------@ 6 lukas staff 192 9 Apr 19:53 .cache\ndrwxr-xr-x 20 lukas staff 640 27 Apr 08:58 .claude\n-rw------- 1 lukas staff 28647 27 Apr 09:12 .claude.json\ndrwxr-xr-x@ 20 lukas staff 640 12 Mar 09:12 .codeium\ndrwxrwxrwx@ 3 lukas staff 96 2 Mar 2023 .composer\ndrwx------ 16 lukas staff 512 21 May 2025 .config\ndrwxr-xr-x 15 lukas staff 480 23 Dec 2024 .continue\ndrwx------@ 3 lukas staff 96 16 Feb 19:13 .copilot\ndrwxr-xr-x@ 5 lukas staff 160 9 Apr 2025 .cursor\ndrwxr-xr-x@ 5 lukas staff 160 17 Aug 2024 .cursor-tutor\ndrwxr-xr-x 3 lukas staff 96 8 Sep 2024 .daytona\ndrwxr-xr-x@ 4 lukas staff 128 18 Feb 10:52 .devdb\ndrwx------ 24 lukas staff 768 27 Apr 18:14 .docker\ndrwx------ 15 lukas staff 480 6 Jun 2023 .dropbox\ndrwxr-xr-x@ 3 lukas staff 96 20 Nov 2022 .fig.dotfiles.bak\n-rw-r--r-- 1 lukas staff 138 5 Mar 2022 .gauth\n-rw-r--r-- 1 lukas staff 220 25 Nov 2021 .gitconfig\n-rw-r--r-- 1 lukas staff 12288 25 Nov 2021 .gitconfig.swp\ndrwx------ 5 lukas staff 160 18 Nov 2021 .hammerspoon\ndrwxr-xr-x 3 lukas staff 96 21 Mar 2025 .idlerc\n-rw------- 1 lukas staff 20 28 Apr 16:51 .lesshst\ndrwx------ 5 lukas staff 160 23 Dec 2024 .local\n-rw------- 1 lukas staff 204 16 Mar 2024 .netrc\ndrwx------ 3 lukas staff 96 1 Nov 2021 .node-gyp\n-rw------- 1 lukas staff 4 6 Feb 2024 .node_repl_history\n-rw-r--r-- 1 lukas staff 17 24 Dec 2023 .notion-enhancer\ndrwxr-xr-x 4 lukas staff 128 12 Jul 2024 .notion-py\ndrwx------ 8 lukas staff 256 6 May 20:24 .npm\n-rw------- 1 lukas staff 74 20 May 2024 .npmrc\ndrwx------ 32 lukas staff 1024 25 Jul 2025 .nvm\ndrwxr-xr-x 4 lukas staff 128 5 Aug 2023 .postman\n-rw-r--r--@ 1 lukas staff 77 9 Feb 2023 .profile\n-rw-------@ 1 lukas staff 3153 21 Mar 2025 .python_history\ndrwx------ 2 lukas staff 64 15 Nov 2021 .quicktype-vscode\ndrwxr-xr-x@ 8 lukas staff 256 16 Feb 08:48 .redis-insight\ndrwxr-xr-x 4 lukas staff 128 4 Feb 09:35 .sonarlint\ndrwx------ 15 lukas staff 480 8 Aug 2025 .ssh\ndrwxr-xr-x@ 3 lukas staff 96 15 Aug 2025 .streamlit\ndrwx------ 6 lukas staff 192 17 Oct 2022 .swiftpm\n-rw------- 1 lukas staff 12143 27 Apr 14:58 .viminfo\ndrwx------ 5 lukas staff 160 19 Jun 2023 .vscode\ndrwxr-xr-x@ 3 lukas staff 96 20 Jan 2025 .warp\n UW PICO 5.09 New Buffer \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n [ Read 1 line ] \n^G Get Help ^O WriteOut ^R Read File ^Y Prev Pg ^K Cut Text ^C Cur Pos \n^X Exit ^J Justify ^W Where is ^V Next Pg ^U UnCut Text ^T To Spell \ndrwxr-xr-x 4 lukas staff 128 29 Apr 2023 .wdm\ndrwxr-xr-x@ 5 lukas staff 160 26 Jan 13:03 .windsurf\ndrwxr-xr-x 4 lukas staff 128 24 Mar 12:03 .yarn\n-rw-r--r-- 1 lukas staff 116 30 Mar 10:12 .yarnrc\n-rw-r--r-- 1 lukas staff 49518 21 Apr 09:09 .zcompdump\n-rw-r--r--@ 1 lukas staff 46758 2 Nov 2025 .zcompdump.Lukas-Kovaliks-MacBook-Pro-Jiminny.23381\n-rw-r--r--@ 1 lukas staff 6116 20 Apr 19:52 .zprofile\n-rw-r--r-- 1 lukas staff 1468 8 Apr 2022 .zprofile-copy\n-rw-r--r--@ 1 lukas staff 2900 15 Mar 2023 .zprofile.pysave\n-rw------- 1 lukas staff 1731 29 Jun 2022 .zprofile.save\n-rw-r--r-- 1 lukas staff 1569 8 Apr 2022 .zprofilees\n-rw------- 1 lukas staff 50310 28 Apr 11:32 .zsh_history\ndrwx------ 9 lukas staff 288 6 May 2025 .zsh_sessions\n-rw-r--r--@ 1 lukas staff 400 18 Apr 13:19 .zshrc\ndrwx------@ 9 lukas staff 288 20 Apr 20:55 Applications\ndrwxr-xr-x@ 2 lukas staff 64 22 Oct 2025 CascadeProjects\ndrwxr-xr-x 4 lukas staff 128 27 Oct 2025 DEV\ndrwx------@ 10 lukas staff 320 28 Apr 18:52 Desktop\ndrwx------@ 7 lukas staff 224 26 Mar 14:40 Documents\ndrwx------@ 44 lukas staff 1408 24 Apr 16:53 Downloads\ndrwxr-xr-x@ 4 lukas staff 128 17 Mar 20:27 Keychron_Screen\ndrwx------@ 112 lukas staff 3584 2 Dec 09:19 Library\ndrwx------ 7 lukas staff 224 12 Feb 2024 Movies\ndrwx------+ 5 lukas staff 160 25 Sep 2023 Music\ndrwx------+ 9 lukas staff 288 25 Sep 2023 Pictures\ndrwx------ 3 lukas staff 96 8 Nov 2021 Postman\ndrwx------+ 4 lukas staff 128 28 Oct 2021 Public\n-rw-r--r--@ 1 lukas staff 3950 15 Dec 09:16 Untitled 4.spf\ndrwx------ 4 lukas staff 128 2 Jul 2023 Users\n-rw-r--r-- 1 lukas staff 17050804 27 Apr 19:18 cleanshot-live.log\n-rw-r--r-- 1 lukas staff 9363061 27 Apr 19:24 cleanshot-screenpipe.log\n-rw-r--r-- 1 lukas staff 0 12 Apr 12:50 clip.mp4\n-rw-r--r-- 1 lukas staff 0 12 Apr 12:51 frame.jpg\ndrwx------ 3 lukas staff 96 30 Sep 2022 iCloud Drive (Archive)\ndrwx------ 16 lukas staff 512 3 Nov 2025 jiminny\ndrwxr-xr-x 3 lukas staff 96 20 Mar 18:47 node_modules\ndrwxr-xr-x 4 lukas staff 128 21 Oct 2025 raycast\n-rw-r--r-- 1 lukas staff 0 1 Mar 14:26 response.bin\n-rwxr-xr-x 1 lukas staff 3824 11 Apr 15:16 screenpipe-day.sh\n-rw-r--r-- 1 lukas staff 86 20 Mar 18:47 yarn.lock\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe\ncd: no such file or directory: /Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ touch screenpipe_sync.sh\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ nano screenpipe_sync.sh\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ npx screenpipe@latest record --ignored-windows \"Boosteroid\" --retention-days 7\ndetected hardware tier: Mid\nwarning: parakeet is not supported on this platform, using whisper-tiny instead\n2026-05-06T20:27:32.721416Z INFO screenpipe_engine::auth_key: api auth: key resolved via auto-generated\nchecking permissions...\n screen recording: ok\n microphone: ok\n accessibility: ok\n2026-05-06T20:27:32.831033Z INFO screenpipe_screen::monitor::macos_version: Detected macOS version: 14.6\n2026-05-06T20:27:34.088403Z INFO screenpipe_engine::sleep_monitor: Starting macOS sleep/wake monitor\n2026-05-06T20:27:34.089942Z INFO screenpipe_engine::sleep_monitor: Screen lock/unlock observers registered (CFNotificationCenter)\n2026-05-06T20:27:34.090417Z INFO screenpipe_engine::sleep_monitor: Display reconfiguration watcher registered (CGDisplayRegisterReconfigurationCallback)\n2026-05-06T20:27:34.112650Z INFO screenpipe_engine::permission_monitor: permission monitor started screen=true mic=true accessibility=true keychain=true\n2026-05-06T20:27:34.112711Z INFO screenpipe: meeting detector enabled — independent of transcription mode\n2026-05-06T20:27:34.619906Z INFO screenpipe: API server listening on 127.0.0.1:3030 (localhost only)\n2026-05-06T20:27:34.619937Z INFO screenpipe: API auth enabled — run `screenpipe auth token` to view your key\n2026-05-06T20:27:34.619857Z INFO screenpipe_engine::snapshot_compaction: snapshot compaction worker started (min_age=600s, poll=300s)\n2026-05-06T20:27:34.619847Z INFO screenpipe_engine::power::manager: power manager started (poll interval: 10s)\n2026-05-06T20:27:34.620018Z INFO screenpipe_engine::vision_manager::manager: Starting VisionManager\n2026-05-06T20:27:34.624746Z INFO screenpipe_core::pipes: installed built-in pipe: day-recap\n2026-05-06T20:27:34.626304Z INFO screenpipe_core::pipes: installed built-in pipe: standup-update\n2026-05-06T20:27:34.628597Z INFO screenpipe_core::pipes: installed built-in pipe: ai-habits\n2026-05-06T20:27:34.629463Z INFO screenpipe_core::pipes: installed built-in pipe: time-breakdown\n2026-05-06T20:27:34.630081Z INFO screenpipe_core::pipes: installed built-in pipe: video-export\n2026-05-06T20:27:34.630972Z INFO screenpipe_core::pipes: installed built-in pipe: meeting-summary\n2026-05-06T20:27:34.631427Z INFO screenpipe_core::pipes: loaded pipe: day-recap\n2026-05-06T20:27:34.631521Z INFO screenpipe_core::pipes: loaded pipe: standup-update\n2026-05-06T20:27:34.631587Z INFO screenpipe_core::pipes: loaded pipe: ai-habits\n2026-05-06T20:27:34.631640Z INFO screenpipe_core::pipes: loaded pipe: time-breakdown\n2026-05-06T20:27:34.631690Z INFO screenpipe_core::pipes: loaded pipe: video-export\n2026-05-06T20:27:34.631738Z INFO screenpipe_core::pipes: loaded pipe: meeting-summary\n2026-05-06T20:27:34.631752Z INFO screenpipe_core::pipes: loaded 6 pipes from \"/Users/lukas/.screenpipe/pipes\"\n\n\n\n _ \n __________________ ___ ____ ____ (_____ ___ \n / ___/ ___/ ___/ _ \\/ _ \\/ __ \\ / __ \\/ / __ \\/ _ \\\n (__ / /__/ / / __/ __/ / / / / /_/ / / /_/ / __/\n/____/\\___/_/ \\___/\\___/_/ /_/ / .___/_/ .___/\\___/ \n /_/ /_/ \n\n\n\npower AI by everything you've seen, said or heard\nopen source | runs locally | developer friendly\n\n\n┌────────────────────────┬────────────────────────────────────┐\n│ setting │ value │\n├────────────────────────┼────────────────────────────────────┤\n│ audio chunk duration │ 30 seconds │\n│ port │ 3030 │\n│ audio disabled │ false │\n│ vision disabled │ false │\n│ pause on DRM content │ false │\n│ audio engine │ Parakeet │\n│ vad engine │ Silero │\n│ data directory │ /Users/lukas/.screenpipe │\n│ debug mode │ false │\n│ telemetry │ true │\n│ use pii removal │ true │\n│ use all monitors │ true │\n│ ignored windows │ [\"Boosteroid\"] │\n│ included windows │ [] │\n│ cloud sync │ disabled │\n│ auto-destruct pid │ 0 │\n│ deepgram key │ not set │\n│ api auth │ enabled │\n│ encrypt secrets │ disabled │\n│ retention days │ 7 │\n│ retention mode │ media-only (keep transcripts) │\n├────────────────────────┼────────────────────────────────────┤\n│ languages │ │\n│ │ all languages │\n├────────────────────────┼────────────────────────────────────┤\n│ monitors │ │\n│ │ id: 1 │\n│ │ id: 2 │\n├────────────────────────┼────────────────────────────────────┤\n│ audio devices │ │\n│ │ MacBook Pro Microphone (input) │\n│ │ System Audio (output) │\n└────────────────────────┴────────────────────────────────────┘\nyou are using local processing. all your data stays on your computer.\n\nwarning: telemetry is enabled. only error-level data will be sent.\nto disable, use the --disable-telemetry flag.\n\ncheck latest changes here: https://github.com/screenpipe/screenpipe/releases\n2026-05-06T20:27:34.638384Z INFO screenpipe: starting UI event capture\n2026-05-06T20:27:34.637679Z INFO screenpipe_core::pipes: pipe scheduler started (generation 2)\n2026-05-06T20:27:34.649154Z INFO screenpipe_engine::power::manager: initial power profile: Performance (on_ac=true, battery=Some(94))\n2026-05-06T20:27:34.652794Z WARN screenpipe: pi agent install failed: bun not found — install from https://bun.sh\n2026-05-06T20:27:34.655839Z INFO screenpipe_engine::ui_recorder: Starting UI event capture\n2026-05-06T20:27:34.673877Z INFO screenpipe_engine::ui_recorder: UI recording session started: 54869993-7b4b-491f-b717-2a583517f9c5\n2026-05-06T20:27:34.673910Z INFO screenpipe_engine::calendar_speaker_id: speaker identification: started (user_name=<not set>)\n2026-05-06T20:27:34.674057Z INFO screenpipe_engine::hot_frame_cache: hot_frame_cache: warming from DB (2026-05-05 17:27:34.674056 UTC to 2026-05-06 17:27:34.674056 UTC)\n2026-05-06T20:27:34.674892Z INFO screenpipe_engine::meeting_detector: meeting v2: detection loop started (base_interval=5s, profiles=12)\n2026-05-06T20:27:34.675788Z INFO screenpipe_engine::hot_frame_cache: hot_frame_cache: warmed with 0 frame entries, coverage from 2026-05-05 17:27:34.674056 UTC\n2026-05-06T20:27:34.686546Z INFO screenpipe_engine::server: Server listening on 127.0.0.1:3030\n2026-05-06T20:27:34.691371Z INFO screenpipe_connect::mdns: mdns: advertising screenpipe on port 3030\n2026-05-06T20:27:36.270608Z INFO screenpipe_engine::vision_manager::manager: Starting vision recording for monitor 1 (1440x900)\n2026-05-06T20:27:36.270669Z INFO screenpipe_engine::vision_manager::manager: Starting event-driven capture for monitor 1 (device: monitor_1)\n2026-05-06T20:27:36.270714Z INFO screenpipe_engine::event_driven_capture: event-driven capture started for monitor 1 (device: monitor_1)\n2026-05-06T20:27:36.932583Z INFO screenpipe_engine::vision_manager::manager: Starting vision recording for monitor 2 (3008x1253)\n2026-05-06T20:27:36.932852Z INFO screenpipe_engine::vision_manager::manager: Starting event-driven capture for monitor 2 (device: monitor_2)\n2026-05-06T20:27:36.932882Z INFO screenpipe_engine::vision_manager::manager: VisionManager started with 2/2 monitor(s)\n2026-05-06T20:27:36.932899Z INFO screenpipe_engine::vision_manager::monitor_watcher: Starting monitor watcher (event-driven via CGDisplayRegisterReconfigurationCallback, 60s backstop poll)\n2026-05-06T20:27:36.932901Z INFO screenpipe_engine::event_driven_capture: event-driven capture started for monitor 2 (device: monitor_2)\n2026-05-06T20:27:39.158281Z INFO sck_rs::stream_manager: persistent SCK stream started for display 1 (1440x900, 2fps, 3 excluded)\n2026-05-06T20:27:39.593177Z INFO screenpipe_engine::event_driven_capture: startup capture for monitor 1: frame_id=1, dur=101ms\n2026-05-06T20:27:40.672366Z INFO sck_rs::stream_manager: persistent SCK stream started for display 2 (3008x1253, 2fps, 3 excluded)\n2026-05-06T20:27:41.257664Z INFO screenpipe_engine::event_driven_capture: startup capture for monitor 2: frame_id=2, dur=140ms\n2026-05-06T20:27:44.641022Z INFO screenpipe_audio::transcription::engine: whisper model available: \"/Users/lukas/.cache/huggingface/hub/models--ggerganov--whisper.cpp/snapshots/5359861c739e955e79d9a303bcbc70fb988958b1/ggml-tiny.bin\"\n2026-05-06T20:27:44.641079Z INFO screenpipe_audio::transcription::whisper::model: whisper context: gpu acceleration enabled (Metal on macOS, Vulkan on Windows)\n2026-05-06T20:27:44.641086Z INFO screenpipe_audio::transcription::engine: loading whisper model with GPU acceleration...\nwhisper_init_from_file_with_params_no_state: loading model from '/Users/lukas/.cache/huggingface/hub/models--ggerganov--whisper.cpp/snapshots/5359861c739e955e79d9a303bcbc70fb988958b1/ggml-tiny.bin'\nwhisper_init_with_params_no_state: use gpu = 1\nwhisper_init_with_params_no_state: flash attn = 0\nwhisper_init_with_params_no_state: gpu_device = 0\nwhisper_init_with_params_no_state: dtw = 0\nggml_metal_device_init: tensor API disabled for pre-M5 and pre-A19 devices\nggml_metal_library_init: using embedded metal library\nggml_metal_library_init: loaded in 0.041 sec\nggml_metal_rsets_init: creating a residency set collection (keep_alive = 180 s)\nggml_metal_device_init: GPU name: Apple M1\nggml_metal_device_init: GPU family: MTLGPUFamilyApple7 (1007)\nggml_metal_device_init: GPU family: MTLGPUFamilyCommon3 (3003)\nggml_metal_device_init: GPU family: MTLGPUFamilyMetal3 (5001)\nggml_metal_device_init: simdgroup reduction = true\nggml_metal_device_init: simdgroup matrix mul. = true\nggml_metal_device_init: has unified memory = true\nggml_metal_device_init: has bfloat = true\nggml_metal_device_init: has tensor = false\nggml_metal_device_init: use residency sets = true\nggml_metal_device_init: use shared buffers = true\nggml_metal_device_init: recommendedMaxWorkingSetSize = 11453.25 MB\nwhisper_init_with_params_no_state: devices = 3\nwhisper_init_with_params_no_state: backends = 3\nwhisper_model_load: loading model\nwhisper_model_load: n_vocab = 51865\nwhisper_model_load: n_audio_ctx = 1500\nwhisper_model_load: n_audio_state = 384\nwhisper_model_load: n_audio_head = 6\nwhisper_model_load: n_audio_layer = 4\nwhisper_model_load: n_text_ctx = 448\nwhisper_model_load: n_text_state = 384\nwhisper_model_load: n_text_head = 6\nwhisper_model_load: n_text_layer = 4\nwhisper_model_load: n_mels = 80\nwhisper_model_load: ftype = 1\nwhisper_model_load: qntvr = 0\nwhisper_model_load: type = 1 (tiny)\nwhisper_model_load: adding 1608 extra tokens\nwhisper_model_load: n_langs = 99\nwhisper_model_load: Metal total size = 77.11 MB\nwhisper_model_load: model size = 77.11 MB\n2026-05-06T20:27:44.857210Z INFO screenpipe_audio::transcription::engine: whisper model loaded successfully\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\n2026-05-06T20:27:44.861912Z INFO screenpipe_audio::audio_manager::manager: transcription session created (will be reused across segments)\n2026-05-06T20:27:44.862480Z INFO screenpipe_audio::audio_manager::manager: audio manager started\n2026-05-06T20:27:44.862525Z INFO screenpipe_audio::audio_manager::manager: calendar-assisted speaker diarization: listening for meeting events\n2026-05-06T20:27:47.831980Z INFO screenpipe_audio::device::device_manager: starting recording for device: System Audio (output)\n2026-05-06T20:27:47.832191Z INFO screenpipe_audio::core::run_record_and_transcribe: starting continuous recording for System Audio (output) (unknown / 30s segments)\n2026-05-06T20:27:47.906029Z INFO screenpipe_audio::device::device_manager: starting recording for device: MacBook Pro Microphone (input)\n2026-05-06T20:27:47.906090Z INFO screenpipe_audio::core::run_record_and_transcribe: starting continuous recording for MacBook Pro Microphone (input) (wired / 30s segments)\n2026-05-06T20:28:15.251258Z INFO screenpipe_engine::event_driven_capture: content dedup: skipping capture for monitor 1 (hash=-8608554010568040663, trigger=visual_change)\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\n2026-05-06T20:29:45.187551Z INFO screenpipe_audio::audio_manager::manager: reconciliation: transcribed 6 orphaned chunks\n2026-05-06T20:30:06.916244Z WARN screenpipe_audio::core::source_buffer: [MacBook Pro Microphone (input)] large gap on wired device: 81.4ms elapsed (expected 5.3ms) → inserting 76.0ms silence (7299 samples)\n2026-05-06T20:30:29.881247Z WARN screenpipe_audio::core::source_buffer: [MacBook Pro Microphone (input)] large gap on wired device: 96.0ms elapsed (expected 5.3ms) → inserting 90.7ms silence (8704 samples)","is_focused":true},{"role":"AXTextField","text":"you","depth":3,"bounds":{"left":0.64793885,"top":1.0,"width":0.0625,"height":-0.07581806},"on_screen":true,"automation_id":"_NS:65","value":"you","role_description":"search text field","subrole":"AXSearchField","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"search","depth":4,"bounds":{"left":0.64860374,"top":1.0,"width":0.00831117,"height":-0.07581806},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"cancel","depth":4,"bounds":{"left":0.7017952,"top":1.0,"width":0.00731383,"height":-0.07581806},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"go left","depth":3,"bounds":{"left":0.7130984,"top":1.0,"width":0.006981383,"height":-0.07661617},"on_screen":true,"automation_id":"_NS:59","role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"go right","depth":3,"bounds":{"left":0.7200798,"top":1.0,"width":0.006981383,"height":-0.07661617},"on_screen":true,"automation_id":"_NS:49","role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXRadioButton","text":"DOCKER","depth":2,"bounds":{"left":0.27027926,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.27227393,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"DEV (docker)","depth":2,"bounds":{"left":0.3487367,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.35073137,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"APP (-zsh)","depth":2,"bounds":{"left":0.42719415,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.42918882,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.5056516,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.50764626,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"screenpipe\"","depth":2,"bounds":{"left":0.58410907,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.58610374,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.6625665,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.66456115,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"⌥⌘1","depth":1,"bounds":{"left":0.7273936,"top":1.0,"width":0.01861702,"height":-0.023144484},"on_screen":true,"automation_id":"_NS:8","role_description":"text"},{"role":"AXStaticText","text":"screenpipe\"","depth":1,"bounds":{"left":0.4956782,"top":1.0,"width":0.027925532,"height":-0.02394259},"on_screen":true,"role_description":"text"}]...
|
7635447758729925822
|
3182944612367924289
|
visual_change
|
accessibility
|
NULL
|
-rw-r--r-- 1 lukas staff 950993 28 Apr 17:45 -rw-r--r-- 1 lukas staff 950993 28 Apr 17:45 compact_monitor_2_1777387552842.mp4
-rw-r--r-- 1 lukas staff 429007 28 Apr 17:51 compact_monitor_2_1777387889075.mp4
-rw-r--r-- 1 lukas staff 884099 28 Apr 17:57 compact_monitor_2_1777388218623.mp4
-rw-r--r-- 1 lukas staff 2352504 28 Apr 18:02 compact_monitor_2_1777388548021.mp4
-rw-r--r-- 1 lukas staff 3298542 28 Apr 18:07 compact_monitor_2_1777388874095.mp4
-rw-r--r-- 1 lukas staff 2143027 28 Apr 18:13 compact_monitor_2_1777389196097.mp4
-rw-r--r-- 1 lukas staff 2448311 28 Apr 18:18 compact_monitor_2_1777389532297.mp4
-rw-r--r-- 1 lukas staff 2780051 28 Apr 18:24 compact_monitor_2_1777389861076.mp4
-rw-r--r-- 1 lukas staff 2715534 28 Apr 18:29 compact_monitor_2_1777390193677.mp4
-rw-r--r-- 1 lukas staff 2102173 28 Apr 18:35 compact_monitor_2_1777390515997.mp4
-rw-r--r-- 1 lukas staff 2324557 28 Apr 18:40 compact_monitor_2_1777390843577.mp4
-rw-r--r-- 1 lukas staff 1525510 28 Apr 18:46 compact_monitor_2_1777391163945.mp4
-rw-r--r-- 1 lukas staff 2776584 28 Apr 18:51 compact_monitor_2_1777391495138.mp4
-rw-r--r-- 1 lukas staff 1168205 28 Apr 18:57 compact_monitor_2_1777391825305.mp4
-rw-r--r-- 1 lukas staff 1736686 28 Apr 19:02 compact_monitor_2_1777392149583.mp4
-rw-r--r-- 1 lukas staff 2133415 28 Apr 19:07 compact_monitor_2_1777392471754.mp4
-rw-r--r-- 1 lukas staff 1289951 28 Apr 19:13 compact_monitor_2_1777392794343.mp4
-rw-r--r-- 1 lukas staff 223494 28 Apr 19:18 compact_monitor_2_1777393110228.mp4
-rw-r--r-- 1 lukas staff 222168 28 Apr 19:23 compact_monitor_2_1777393424109.mp4
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-04-28 $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22523176
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 28 Apr 16:51 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11525263360 28 Apr 19:33 db.sqlite
-rw-r--r-- 1 lukas staff 65536 28 Apr 15:26 db.sqlite-shm
-rw-r--r-- 1 lukas staff 2323712 28 Apr 22:23 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34227 26 Apr 17:01 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ~/.screenpipe/screenpipe_sync.sh 2026-04-27
[2026-05-06 18:58:18] ========================================
[2026-05-06 18:58:18] Screenpipe sync starting for: 2026-04-27
[2026-05-06 18:58:18] ========================================
[+00m00s] ▶ Preflight checks
Source DB: OK ( 11G)
NAS mount: OK /Volumes/screenpipe
Archive DB: exists (7.7G)
Data dir: OK (242 files, 325M)
[+00m04s] ▶ Counting source rows for 2026-04-27
frames: 7543
elements: 470235
ui_events: 9909
ocr_text: 2193
meetings: 3
[+00m06s] ▶ Initialising tables, indexes, FTS
creating tables ✓ 0m00s
creating indexes ✓ 0m01s
creating FTS tables ✓ 0m00s
[+00m07s] ▶ Syncing data for 2026-04-27
video_chunks ✓ 0m11s
frames (7543 rows) ⠧ Runtime error near line 3: disk I/O error (10)
frames (7543 rows) ⠴ %
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ~/.screenpipe/screenpipe_sync.sh 2026-04-27
[2026-05-06 19:22:16] ========================================
[2026-05-06 19:22:16] Screenpipe sync starting for: 2026-04-27
[2026-05-06 19:22:16] ========================================
[+00m00s] ▶ Preflight checks
Source DB: OK ( 11G)
NAS mount: OK /Volumes/screenpipe
Archive DB: exists (7.7G)
Data dir: OK (242 files, 325M)
[+00m01s] ▶ Counting source rows for 2026-04-27
frames: 7543
elements: 470235
ui_events: 9909
ocr_text: 2193
meetings: 3
[+00m02s] ▶ Initialising tables, indexes, FTS
creating tables ✓ 0m00s
creating indexes ✓ 0m01s
creating FTS tables ✓ 0m00s
[+00m03s] ▶ Syncing data for 2026-04-27
video_chunks ✓ 0m11s
frames (7543 rows) ✓ 4m40s
ocr_text (2193 rows) ✓ 0m25s
ui_events (9909 rows) ✓ 0m02s
elements (470235 rows) ✓ 2m46s
meetings (3 rows) ✓ 0m00s
[+08m07s] ▶ Updating FTS indexes
elements_fts ✓ 2m59s
frames_fts ✓ 6m07s
ui_events_fts ✓ 0m03s
[+17m16s] ▶ Verifying DB
frames: 7543 / 7543 ✓
elements: 470235 / 470235 ✓
ui_events: 9909 / 9909 ✓
ocr_text: 2193 / 2193 ✓
meetings: 3 / 3 ✓
[+18m46s] ▶ Copying data folder for 2026-04-27
rsync 2026-04-27/ → NAS ✓ 0m26s (242 files, 325M)
[2026-05-06 19:41:28] Archive DB size: 9.7G
[2026-05-06 19:41:28] Total time: 19m12s
[2026-05-06 19:41:28] Sync complete for 2026-04-27
[2026-05-06 19:41:28] ========================================
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ~/.screenpipe/screenpipe_sync.sh 2026-04-28
[2026-05-06 19:44:49] ========================================
[2026-05-06 19:44:49] Screenpipe sync starting for: 2026-04-28
[2026-05-06 19:44:49] ========================================
[+00m00s] ▶ Preflight checks
Source DB: OK ( 11G)
NAS mount: OK /Volumes/screenpipe
Archive DB: exists (9.7G)
Data dir: OK (223 files, 159M)
[+00m00s] ▶ Counting source rows for 2026-04-28
frames: 4535
elements: 407532
ui_events: 8621
ocr_text: 1623
meetings: 3
[+00m02s] ▶ Initialising tables, indexes, FTS
creating tables ✓ 0m00s
creating indexes ✓ 0m00s
creating FTS tables ✓ 0m00s
[+00m02s] ▶ Syncing data for 2026-04-28
video_chunks ✓ 0m12s
frames (4535 rows) ✓ 1m30s
ocr_text (1623 rows) ✓ 0m32s
ui_events (8621 rows) ✓ 0m01s
elements (407532 rows) ✓ 1m02s
meetings (3 rows) ✓ 0m00s
[+03m19s] ▶ Updating FTS indexes
elements_fts ✓ 1m36s
frames_fts ✓ 2m28s
ui_events_fts ✓ 0m04s
[+07m27s] ▶ Verifying DB
frames: 4535 / 4535 ✓
elements: 407532 / 407532 ✓
ui_events: 8621 / 8621 ✓
ocr_text: 1623 / 1623 ✓
meetings: 3 / 3 ✓
[+08m59s] ▶ Copying data folder for 2026-04-28
rsync 2026-04-28/ → NAS ✓ 0m20s (223 files, 159M)
[2026-05-06 19:54:08] Archive DB size: 10G
[2026-05-06 19:54:08] Total time: 9m19s
[2026-05-06 19:54:08] Sync complete for 2026-04-28
[2026-05-06 19:54:08] ========================================
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ pkill -f screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ rm -rf ~/.screenpipe/
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 92 lukas staff 2944 6 May 20:22 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd .npm
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ ll
total 24
drwx------ 9 lukas staff 288 28 Apr 09:18 .
drwx------+ 92 lukas staff 2944 6 May 20:22 ..
drwx------ 5 lukas staff 160 1 Nov 2021 _cacache
drwx------@ 2 lukas staff 64 28 Apr 09:18 _locks
drwx------ 15 lukas staff 480 27 Apr 19:54 _logs
drwxr-xr-x 67 lukas staff 2144 28 Apr 09:17 _npx
-rw-r--r--@ 1 lukas staff 0 26 Apr 19:10 _update-notifier-last-checked
-rw-r--r-- 1 lukas staff 173 28 Apr 09:18 anonymous-cli-metrics.json
-rw-r--r-- 1 lukas staff 4764 31 Jan 2024 eresolve-report.txt
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ rm -rf ~/.npm/_npx
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ ll
total 52920
drwx------+ 92 lukas staff 2944 6 May 20:22 .
drwxr-xr-x 5 root admin 160 23 Aug 2024 ..
-r-------- 1 lukas staff 7 18 Nov 2021 .CFUserTextEncoding
-rw-r--r--@ 1 lukas staff 28676 27 Apr 09:11 .DS_Store
drwx------+ 10 lukas staff 320 28 Apr 17:07 .Trash
drwx------ 5 lukas staff 160 1 Nov 2021 .aws
-rw-r--r-- 1 lukas staff 341470 29 Sep 2022 .babel.json
-rw-------@ 1 lukas staff 388 25 Jul 2025 .bash_history
-rw-r--r--@ 1 lukas staff 115 18 Apr 13:19 .bashrc
drwxr-xr-x 5 lukas staff 160 11 Mar 2023 .bito
drwx------@ 6 lukas staff 192 9 Apr 19:53 .cache
drwxr-xr-x 20 lukas staff 640 27 Apr 08:58 .claude
-rw------- 1 lukas staff 28647 27 Apr 09:12 .claude.json
drwxr-xr-x@ 20 lukas staff 640 12 Mar 09:12 .codeium
drwxrwxrwx@ 3 lukas staff 96 2 Mar 2023 .composer
drwx------ 16 lukas staff 512 21 May 2025 .config
drwxr-xr-x 15 lukas staff 480 23 Dec 2024 .continue
drwx------@ 3 lukas staff 96 16 Feb 19:13 .copilot
drwxr-xr-x@ 5 lukas staff 160 9 Apr 2025 .cursor
drwxr-xr-x@ 5 lukas staff 160 17 Aug 2024 .cursor-tutor
drwxr-xr-x 3 lukas staff 96 8 Sep 2024 .daytona
drwxr-xr-x@ 4 lukas staff 128 18 Feb 10:52 .devdb
drwx------ 24 lukas staff 768 27 Apr 18:14 .docker
drwx------ 15 lukas staff 480 6 Jun 2023 .dropbox
drwxr-xr-x@ 3 lukas staff 96 20 Nov 2022 .fig.dotfiles.bak
-rw-r--r-- 1 lukas staff 138 5 Mar 2022 .gauth
-rw-r--r-- 1 lukas staff 220 25 Nov 2021 .gitconfig
-rw-r--r-- 1 lukas staff 12288 25 Nov 2021 .gitconfig.swp
drwx------ 5 lukas staff 160 18 Nov 2021 .hammerspoon
drwxr-xr-x 3 lukas staff 96 21 Mar 2025 .idlerc
-rw------- 1 lukas staff 20 28 Apr 16:51 .lesshst
drwx------ 5 lukas staff 160 23 Dec 2024 .local
-rw------- 1 lukas staff 204 16 Mar 2024 .netrc
drwx------ 3 lukas staff 96 1 Nov 2021 .node-gyp
-rw------- 1 lukas staff 4 6 Feb 2024 .node_repl_history
-rw-r--r-- 1 lukas staff 17 24 Dec 2023 .notion-enhancer
drwxr-xr-x 4 lukas staff 128 12 Jul 2024 .notion-py
drwx------ 8 lukas staff 256 6 May 20:24 .npm
-rw------- 1 lukas staff 74 20 May 2024 .npmrc
drwx------ 32 lukas staff 1024 25 Jul 2025 .nvm
drwxr-xr-x 4 lukas staff 128 5 Aug 2023 .postman
-rw-r--r--@ 1 lukas staff 77 9 Feb 2023 .profile
-rw-------@ 1 lukas staff 3153 21 Mar 2025 .python_history
drwx------ 2 lukas staff 64 15 Nov 2021 .quicktype-vscode
drwxr-xr-x@ 8 lukas staff 256 16 Feb 08:48 .redis-insight
drwxr-xr-x 4 lukas staff 128 4 Feb 09:35 .sonarlint
drwx------ 15 lukas staff 480 8 Aug 2025 .ssh
drwxr-xr-x@ 3 lukas staff 96 15 Aug 2025 .streamlit
drwx------ 6 lukas staff 192 17 Oct 2022 .swiftpm
-rw------- 1 lukas staff 12143 27 Apr 14:58 .viminfo
drwx------ 5 lukas staff 160 19 Jun 2023 .vscode
drwxr-xr-x@ 3 lukas staff 96 20 Jan 2025 .warp
UW PICO 5.09 New Buffer
[ Read 1 line ]
^G Get Help ^O WriteOut ^R Read File ^Y Prev Pg ^K Cut Text ^C Cur Pos
^X Exit ^J Justify ^W Where is ^V Next Pg ^U UnCut Text ^T To Spell
drwxr-xr-x 4 lukas staff 128 29 Apr 2023 .wdm
drwxr-xr-x@ 5 lukas staff 160 26 Jan 13:03 .windsurf
drwxr-xr-x 4 lukas staff 128 24 Mar 12:03 .yarn
-rw-r--r-- 1 lukas staff 116 30 Mar 10:12 .yarnrc
-rw-r--r-- 1 lukas staff 49518 21 Apr 09:09 .zcompdump
-rw-r--r--@ 1 lukas staff 46758 2 Nov 2025 .zcompdump.Lukas-Kovaliks-MacBook-Pro-Jiminny.23381
-rw-r--r--@ 1 lukas staff 6116 20 Apr 19:52 .zprofile
-rw-r--r-- 1 lukas staff 1468 8 Apr 2022 .zprofile-copy
-rw-r--r--@ 1 lukas staff 2900 15 Mar 2023 .zprofile.pysave
-rw------- 1 lukas staff 1731 29 Jun 2022 .zprofile.save
-rw-r--r-- 1 lukas staff 1569 8 Apr 2022 .zprofilees
-rw------- 1 lukas staff 50310 28 Apr 11:32 .zsh_history
drwx------ 9 lukas staff 288 6 May 2025 .zsh_sessions
-rw-r--r--@ 1 lukas staff 400 18 Apr 13:19 .zshrc
drwx------@ 9 lukas staff 288 20 Apr 20:55 Applications
drwxr-xr-x@ 2 lukas staff 64 22 Oct 2025 CascadeProjects
drwxr-xr-x 4 lukas staff 128 27 Oct 2025 DEV
drwx------@ 10 lukas staff 320 28 Apr 18:52 Desktop
drwx------@ 7 lukas staff 224 26 Mar 14:40 Documents
drwx------@ 44 lukas staff 1408 24 Apr 16:53 Downloads
drwxr-xr-x@ 4 lukas staff 128 17 Mar 20:27 Keychron_Screen
drwx------@ 112 lukas staff 3584 2 Dec 09:19 Library
drwx------ 7 lukas staff 224 12 Feb 2024 Movies
drwx------+ 5 lukas staff 160 25 Sep 2023 Music
drwx------+ 9 lukas staff 288 25 Sep 2023 Pictures
drwx------ 3 lukas staff 96 8 Nov 2021 Postman
drwx------+ 4 lukas staff 128 28 Oct 2021 Public
-rw-r--r--@ 1 lukas staff 3950 15 Dec 09:16 Untitled 4.spf
drwx------ 4 lukas staff 128 2 Jul 2023 Users
-rw-r--r-- 1 lukas staff 17050804 27 Apr 19:18 cleanshot-live.log
-rw-r--r-- 1 lukas staff 9363061 27 Apr 19:24 cleanshot-screenpipe.log
-rw-r--r-- 1 lukas staff 0 12 Apr 12:50 clip.mp4
-rw-r--r-- 1 lukas staff 0 12 Apr 12:51 frame.jpg
drwx------ 3 lukas staff 96 30 Sep 2022 iCloud Drive (Archive)
drwx------ 16 lukas staff 512 3 Nov 2025 jiminny
drwxr-xr-x 3 lukas staff 96 20 Mar 18:47 node_modules
drwxr-xr-x 4 lukas staff 128 21 Oct 2025 raycast
-rw-r--r-- 1 lukas staff 0 1 Mar 14:26 response.bin
-rwxr-xr-x 1 lukas staff 3824 11 Apr 15:16 screenpipe-day.sh
-rw-r--r-- 1 lukas staff 86 20 Mar 18:47 yarn.lock
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
cd: no such file or directory: /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ touch screenpipe_sync.sh
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ nano screenpipe_sync.sh
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ npx screenpipe@latest record --ignored-windows "Boosteroid" --retention-days 7
detected hardware tier: Mid
warning: parakeet is not supported on this platform, using whisper-tiny instead
2026-05-06T20:27:32.721416Z INFO screenpipe_engine::auth_key: api auth: key resolved via auto-generated
checking permissions...
screen recording: ok
microphone: ok
accessibility: ok
2026-05-06T20:27:32.831033Z INFO screenpipe_screen::monitor::macos_version: Detected macOS version: 14.6
2026-05-06T20:27:34.088403Z INFO screenpipe_engine::sleep_monitor: Starting macOS sleep/wake monitor
2026-05-06T20:27:34.089942Z INFO screenpipe_engine::sleep_monitor: Screen lock/unlock observers registered (CFNotificationCenter)
2026-05-06T20:27:34.090417Z INFO screenpipe_engine::sleep_monitor: Display reconfiguration watcher registered (CGDisplayRegisterReconfigurationCallback)
2026-05-06T20:27:34.112650Z INFO screenpipe_engine::permission_monitor: permission monitor started screen=true mic=true accessibility=true keychain=true
2026-05-06T20:27:34.112711Z INFO screenpipe: meeting detector enabled — independent of transcription mode
2026-05-06T20:27:34.619906Z INFO screenpipe: API server listening on [IP_ADDRESS]:3030 (localhost only)
2026-05-06T20:27:34.619937Z INFO screenpipe: API auth enabled — run `screenpipe auth token` to view your key
2026-05-06T20:27:34.619857Z INFO screenpipe_engine::snapshot_compaction: snapshot compaction worker started (min_age=600s, poll=300s)
2026-05-06T20:27:34.619847Z INFO screenpipe_engine::power::manager: power manager started (poll interval: 10s)
2026-05-06T20:27:34.620018Z INFO screenpipe_engine::vision_manager::manager: Starting VisionManager
2026-05-06T20:27:34.624746Z INFO screenpipe_core::pipes: installed built-in pipe: day-recap
2026-05-06T20:27:34.626304Z INFO screenpipe_core::pipes: installed built-in pipe: standup-update
2026-05-06T20:27:34.628597Z INFO screenpipe_core::pipes: installed built-in pipe: ai-habits
2026-05-06T20:27:34.629463Z INFO screenpipe_core::pipes: installed built-in pipe: time-breakdown
2026-05-06T20:27:34.630081Z INFO screenpipe_core::pipes: installed built-in pipe: video-export
2026-05-06T20:27:34.630972Z INFO screenpipe_core::pipes: installed built-in pipe: meeting-summary
2026-05-06T20:27:34.631427Z INFO screenpipe_core::pipes: loaded pipe: day-recap
2026-05-06T20:27:34.631521Z INFO screenpipe_core::pipes: loaded pipe: standup-update
2026-05-06T20:27:34.631587Z INFO screenpipe_core::pipes: loaded pipe: ai-habits
2026-05-06T20:27:34.631640Z INFO screenpipe_core::pipes: loaded pipe: time-breakdown
2026-05-06T20:27:34.631690Z INFO screenpipe_core::pipes: loaded pipe: video-export
2026-05-06T20:27:34.631738Z INFO screenpipe_core::pipes: loaded pipe: meeting-summary
2026-05-06T20:27:34.631752Z INFO screenpipe_core::pipes: loaded 6 pipes from "/Users/lukas/.screenpipe/pipes"
_
__________________ ___ ____ ____ (_____ ___
/ ___/ ___/ ___/ _ \/ _ \/ __ \ / __ \/ / __ \/ _ \
(__ / /__/ / / __/ __/ / / / / /_/ / / /_/ / __/
/____/\___/_/ \___/\___/_/ /_/ / .___/_/ .___/\___/
/_/ /_/
power AI by everything you've seen, said or heard
open source | runs locally | developer friendly
┌────────────────────────┬────────────────────────────────────┐
│ setting │ value │
├────────────────────────┼────────────────────────────────────┤
│ audio chunk duration │ 30 seconds │
│ port │ 3030 │
│ audio disabled │ false │
│ vision disabled │ false │
│ pause on DRM content │ false │
│ audio engine │ Parakeet │
│ vad engine │ Silero │
│ data directory │ /Users/lukas/.screenpipe │
│ debug mode │ false │
│ telemetry │ true │
│ use pii removal │ true │
│ use all monitors │ true │
│ ignored windows │ ["Boosteroid"] │
│ included windows │ [] │
│ cloud sync │ disabled │
│ auto-destruct pid │ 0 │
│ deepgram key │ not set │
│ api auth │ enabled │
│ encrypt secrets │ disabled │
│ retention days │ 7 │
│ retention mode │ media-only (keep transcripts) │
├────────────────────────┼────────────────────────────────────┤
│ languages │ │
│ │ all languages │
├────────────────────────┼────────────────────────────────────┤
│ monitors │ │
│ │ id: 1 │
│ │ id: 2 │
├────────────────────────┼────────────────────────────────────┤
│ audio devices │ │
│ │ MacBook Pro Microphone (input) │
│ │ System Audio (output) │
└────────────────────────┴────────────────────────────────────┘
you are using local processing. all your data stays on your computer.
warning: telemetry is enabled. only error-level data will be sent.
to disable, use the --disable-telemetry flag.
check latest changes here: https://github.com/screenpipe/screenpipe/releases
2026-05-06T20:27:34.638384Z INFO screenpipe: starting UI event capture
2026-05-06T20:27:34.637679Z INFO screenpipe_core::pipes: pipe scheduler started (generation 2)
2026-05-06T20:27:34.649154Z INFO screenpipe_engine::power::manager: initial power profile: Performance (on_ac=true, battery=Some(94))
2026-05-06T20:27:34.652794Z WARN screenpipe: pi agent install failed: bun not found — install from https://bun.sh
2026-05-06T20:27:34.655839Z INFO screenpipe_engine::ui_recorder: Starting UI event capture
2026-05-06T20:27:34.673877Z INFO screenpipe_engine::ui_recorder: UI recording session started: 54869993-7b4b-491f-b717-2a583517f9c5
2026-05-06T20:27:34.673910Z INFO screenpipe_engine::calendar_speaker_id: speaker identification: started (user_name=<not set>)
2026-05-06T20:27:34.674057Z INFO screenpipe_engine::hot_frame_cache: hot_frame_cache: warming from DB (2026-05-05 17:27:34.674056 UTC to 2026-05-06 17:27:34.674056 UTC)
2026-05-06T20:27:34.674892Z INFO screenpipe_engine::meeting_detector: meeting v2: detection loop started (base_interval=5s, profiles=12)
2026-05-06T20:27:34.675788Z INFO screenpipe_engine::hot_frame_cache: hot_frame_cache: warmed with 0 frame entries, coverage from 2026-05-05 17:27:34.674056 UTC
2026-05-06T20:27:34.686546Z INFO screenpipe_engine::server: Server listening on [IP_ADDRESS]:3030
2026-05-06T20:27:34.691371Z INFO screenpipe_connect::mdns: mdns: advertising screenpipe on port 3030
2026-05-06T20:27:36.270608Z INFO screenpipe_engine::vision_manager::manager: Starting vision recording for monitor 1 (1440x900)
2026-05-06T20:27:36.270669Z INFO screenpipe_engine::vision_manager::manager: Starting event-driven capture for monitor 1 (device: monitor_1)
2026-05-06T20:27:36.270714Z INFO screenpipe_engine::event_driven_capture: event-driven capture started for monitor 1 (device: monitor_1)
2026-05-06T20:27:36.932583Z INFO screenpipe_engine::vision_manager::manager: Starting vision recording for monitor 2 (3008x1253)
2026-05-06T20:27:36.932852Z INFO screenpipe_engine::vision_manager::manager: Starting event-driven capture for monitor 2 (device: monitor_2)
2026-05-06T20:27:36.932882Z INFO screenpipe_engine::vision_manager::manager: VisionManager started with 2/2 monitor(s)
2026-05-06T20:27:36.932899Z INFO screenpipe_engine::vision_manager::monitor_watcher: Starting monitor watcher (event-driven via CGDisplayRegisterReconfigurationCallback, 60s backstop poll)
2026-05-06T20:27:36.932901Z INFO screenpipe_engine::event_driven_capture: event-driven capture started for monitor 2 (device: monitor_2)
2026-05-06T20:27:39.158281Z INFO sck_rs::stream_manager: persistent SCK stream started for display 1 (1440x900, 2fps, 3 excluded)
2026-05-06T20:27:39.593177Z INFO screenpipe_engine::event_driven_capture: startup capture for monitor 1: frame_id=1, dur=101ms
2026-05-06T20:27:40.672366Z INFO sck_rs::stream_manager: persistent SCK stream started for display 2 (3008x1253, 2fps, 3 excluded)
2026-05-06T20:27:41.257664Z INFO screenpipe_engine::event_driven_capture: startup capture for monitor 2: frame_id=2, dur=140ms
2026-05-06T20:27:44.641022Z INFO screenpipe_audio::transcription::engine: whisper model available: "/Users/lukas/.cache/huggingface/hub/models--ggerganov--whisper.cpp/snapshots/5359861c739e955e79d9a303bcbc70fb988958b1/ggml-tiny.bin"
2026-05-06T20:27:44.641079Z INFO screenpipe_audio::transcription::whisper::model: whisper context: gpu acceleration enabled (Metal on macOS, Vulkan on Windows)
2026-05-06T20:27:44.641086Z INFO screenpipe_audio::transcription::engine: loading whisper model with GPU acceleration...
whisper_init_from_file_with_params_no_state: loading model from '/Users/lukas/.cache/huggingface/hub/models--ggerganov--whisper.cpp/snapshots/5359861c739e955e79d9a303bcbc70fb988958b1/ggml-tiny.bin'
whisper_init_with_params_no_state: use gpu = 1
whisper_init_with_params_no_state: flash attn = 0
whisper_init_with_params_no_state: gpu_device = 0
whisper_init_with_params_no_state: dtw = 0
ggml_metal_device_init: tensor API disabled for pre-M5 and pre-A19 devices
ggml_metal_library_init: using embedded metal library
ggml_metal_library_init: loaded in 0.041 sec
ggml_metal_rsets_init: creating a residency set collection (keep_alive = 180 s)
ggml_metal_device_init: GPU name: Apple M1
ggml_metal_device_init: GPU family: MTLGPUFamilyApple7 (1007)
ggml_metal_device_init: GPU family: MTLGPUFamilyCommon3 (3003)
ggml_metal_device_init: GPU family: MTLGPUFamilyMetal3 (5001)
ggml_metal_device_init: simdgroup reduction = true
ggml_metal_device_init: simdgroup matrix mul. = true
ggml_metal_device_init: has unified memory = true
ggml_metal_device_init: has bfloat = true
ggml_metal_device_init: has tensor = false
ggml_metal_device_init: use residency sets = true
ggml_metal_device_init: use shared buffers = true
ggml_metal_device_init: recommendedMaxWorkingSetSize = 11453.25 MB
whisper_init_with_params_no_state: devices = 3
whisper_init_with_params_no_state: backends = 3
whisper_model_load: loading model
whisper_model_load: n_vocab = 51865
whisper_model_load: n_audio_ctx = 1500
whisper_model_load: n_audio_state = 384
whisper_model_load: n_audio_head = 6
whisper_model_load: n_audio_layer = 4
whisper_model_load: n_text_ctx = 448
whisper_model_load: n_text_state = 384
whisper_model_load: n_text_head = 6
whisper_model_load: n_text_layer = 4
whisper_model_load: n_mels = 80
whisper_model_load: ftype = 1
whisper_model_load: qntvr = 0
whisper_model_load: type = 1 (tiny)
whisper_model_load: adding 1608 extra tokens
whisper_model_load: n_langs = 99
whisper_model_load: Metal total size = 77.11 MB
whisper_model_load: model size = 77.11 MB
2026-05-06T20:27:44.857210Z INFO screenpipe_audio::transcription::engine: whisper model loaded successfully
whisper_backend_init_gpu: device 0: Metal (type: 1)
whisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)
whisper_backend_init_gpu: using Metal backend
ggml_metal_init: allocating
ggml_metal_init: found device: Apple M1
ggml_metal_init: picking default device: Apple M1
ggml_metal_init: use fusion = true
ggml_metal_init: use concurrency = true
ggml_metal_init: use graph optimize = true
whisper_backend_init: using BLAS backend
whisper_init_state: kv self size = 3.15 MB
whisper_init_state: kv cross size = 9.44 MB
whisper_init_state: kv pad size = 2.36 MB
whisper_init_state: compute buffer (conv) = 14.17 MB
whisper_init_state: compute buffer (encode) = 65.96 MB
whisper_init_state: compute buffer (cross) = 8.50 MB
whisper_init_state: compute buffer (decode) = 96.83 MB
2026-05-06T20:27:44.861912Z INFO screenpipe_audio::audio_manager::manager: transcription session created (will be reused across segments)
2026-05-06T20:27:44.862480Z INFO screenpipe_audio::audio_manager::manager: audio manager started
2026-05-06T20:27:44.862525Z INFO screenpipe_audio::audio_manager::manager: calendar-assisted speaker diarization: listening for meeting events
2026-05-06T20:27:47.831980Z INFO screenpipe_audio::device::device_manager: starting recording for device: System Audio (output)
2026-05-06T20:27:47.832191Z INFO screenpipe_audio::core::run_record_and_transcribe: starting continuous recording for System Audio (output) (unknown / 30s segments)
2026-05-06T20:27:47.906029Z INFO screenpipe_audio::device::device_manager: starting recording for device: MacBook Pro Microphone (input)
2026-05-06T20:27:47.906090Z INFO screenpipe_audio::core::run_record_and_transcribe: starting continuous recording for MacBook Pro Microphone (input) (wired / 30s segments)
2026-05-06T20:28:15.251258Z INFO screenpipe_engine::event_driven_capture: content dedup: skipping capture for monitor 1 (hash=-8608554010568040663, trigger=visual_change)
whisper_backend_init_gpu: device 0: Metal (type: 1)
whisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)
whisper_backend_init_gpu: using Metal backend
ggml_metal_init: allocating
ggml_metal_init: found device: Apple M1
ggml_metal_init: picking default device: Apple M1
ggml_metal_init: use fusion = true
ggml_metal_init: use concurrency = true
ggml_metal_init: use graph optimize = true
whisper_backend_init: using BLAS backend
whisper_init_state: kv self size = 3.15 MB
whisper_init_state: kv cross size = 9.44 MB
whisper_init_state: kv pad size = 2.36 MB
whisper_init_state: compute buffer (conv) = 14.17 MB
whisper_init_state: compute buffer (encode) = 65.96 MB
whisper_init_state: compute buffer (cross) = 8.50 MB
whisper_init_state: compute buffer (decode) = 96.83 MB
ggml_metal_free: deallocating
whisper_backend_init_gpu: device 0: Metal (type: 1)
whisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)
whisper_backend_init_gpu: using Metal backend
ggml_metal_init: allocating
ggml_metal_init: found device: Apple M1
ggml_metal_init: picking default device: Apple M1
ggml_metal_init: use fusion = true
ggml_metal_init: use concurrency = true
ggml_metal_init: use graph optimize = true
whisper_backend_init: using BLAS backend
whisper_init_state: kv self size = 3.15 MB
whisper_init_state: kv cross size = 9.44 MB
whisper_init_state: kv pad size = 2.36 MB
whisper_init_state: compute buffer (conv) = 14.17 MB
whisper_init_state: compute buffer (encode) = 65.96 MB
whisper_init_state: compute buffer (cross) = 8.50 MB
whisper_init_state: compute buffer (decode) = 96.83 MB
ggml_metal_free: deallocating
whisper_backend_init_gpu: device 0: Metal (type: 1)
whisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)
whisper_backend_init_gpu: using Metal backend
ggml_metal_init: allocating
ggml_metal_init: found device: Apple M1
ggml_metal_init: picking default device: Apple M1
ggml_metal_init: use fusion = true
ggml_metal_init: use concurrency = true
ggml_metal_init: use graph optimize = true
whisper_backend_init: using BLAS backend
whisper_init_state...
|
49
|
NULL
|
NULL
|
NULL
|
|
52
|
3
|
12
|
2026-05-06T17:31:43.280460+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778088703280_m1.jpg...
|
iTerm2
|
screenpipe"
|
True
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
-rw-r--r-- 1 lukas staff 3298542 28 Apr 18:07 -rw-r--r-- 1 lukas staff 3298542 28 Apr 18:07 compact_monitor_2_1777388874095.mp4
-rw-r--r-- 1 lukas staff 2143027 28 Apr 18:13 compact_monitor_2_1777389196097.mp4
-rw-r--r-- 1 lukas staff 2448311 28 Apr 18:18 compact_monitor_2_1777389532297.mp4
-rw-r--r-- 1 lukas staff 2780051 28 Apr 18:24 compact_monitor_2_1777389861076.mp4
-rw-r--r-- 1 lukas staff 2715534 28 Apr 18:29 compact_monitor_2_1777390193677.mp4
-rw-r--r-- 1 lukas staff 2102173 28 Apr 18:35 compact_monitor_2_1777390515997.mp4
-rw-r--r-- 1 lukas staff 2324557 28 Apr 18:40 compact_monitor_2_1777390843577.mp4
-rw-r--r-- 1 lukas staff 1525510 28 Apr 18:46 compact_monitor_2_1777391163945.mp4
-rw-r--r-- 1 lukas staff 2776584 28 Apr 18:51 compact_monitor_2_1777391495138.mp4
-rw-r--r-- 1 lukas staff 1168205 28 Apr 18:57 compact_monitor_2_1777391825305.mp4
-rw-r--r-- 1 lukas staff 1736686 28 Apr 19:02 compact_monitor_2_1777392149583.mp4
-rw-r--r-- 1 lukas staff 2133415 28 Apr 19:07 compact_monitor_2_1777392471754.mp4
-rw-r--r-- 1 lukas staff 1289951 28 Apr 19:13 compact_monitor_2_1777392794343.mp4
-rw-r--r-- 1 lukas staff 223494 28 Apr 19:18 compact_monitor_2_1777393110228.mp4
-rw-r--r-- 1 lukas staff 222168 28 Apr 19:23 compact_monitor_2_1777393424109.mp4
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-04-28 $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22523176
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 28 Apr 16:51 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11525263360 28 Apr 19:33 db.sqlite
-rw-r--r-- 1 lukas staff 65536 28 Apr 15:26 db.sqlite-shm
-rw-r--r-- 1 lukas staff 2323712 28 Apr 22:23 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34227 26 Apr 17:01 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ~/.screenpipe/screenpipe_sync.sh 2026-04-27
[2026-05-06 18:58:18] ========================================
[2026-05-06 18:58:18] Screenpipe sync starting for: 2026-04-27
[2026-05-06 18:58:18] ========================================
[+00m00s] ▶ Preflight checks
Source DB: OK ( 11G)
NAS mount: OK /Volumes/screenpipe
Archive DB: exists (7.7G)
Data dir: OK (242 files, 325M)
[+00m04s] ▶ Counting source rows for 2026-04-27
frames: 7543
elements: 470235
ui_events: 9909
ocr_text: 2193
meetings: 3
[+00m06s] ▶ Initialising tables, indexes, FTS
creating tables ✓ 0m00s
creating indexes ✓ 0m01s
creating FTS tables ✓ 0m00s
[+00m07s] ▶ Syncing data for 2026-04-27
video_chunks ✓ 0m11s
frames (7543 rows) ⠧ Runtime error near line 3: disk I/O error (10)
frames (7543 rows) ⠴ %
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ~/.screenpipe/screenpipe_sync.sh 2026-04-27
[2026-05-06 19:22:16] ========================================
[2026-05-06 19:22:16] Screenpipe sync starting for: 2026-04-27
[2026-05-06 19:22:16] ========================================
[+00m00s] ▶ Preflight checks
Source DB: OK ( 11G)
NAS mount: OK /Volumes/screenpipe
Archive DB: exists (7.7G)
Data dir: OK (242 files, 325M)
[+00m01s] ▶ Counting source rows for 2026-04-27
frames: 7543
elements: 470235
ui_events: 9909
ocr_text: 2193
meetings: 3
[+00m02s] ▶ Initialising tables, indexes, FTS
creating tables ✓ 0m00s
creating indexes ✓ 0m01s
creating FTS tables ✓ 0m00s
[+00m03s] ▶ Syncing data for 2026-04-27
video_chunks ✓ 0m11s
frames (7543 rows) ✓ 4m40s
ocr_text (2193 rows) ✓ 0m25s
ui_events (9909 rows) ✓ 0m02s
elements (470235 rows) ✓ 2m46s
meetings (3 rows) ✓ 0m00s
[+08m07s] ▶ Updating FTS indexes
elements_fts ✓ 2m59s
frames_fts ✓ 6m07s
ui_events_fts ✓ 0m03s
[+17m16s] ▶ Verifying DB
frames: 7543 / 7543 ✓
elements: 470235 / 470235 ✓
ui_events: 9909 / 9909 ✓
ocr_text: 2193 / 2193 ✓
meetings: 3 / 3 ✓
[+18m46s] ▶ Copying data folder for 2026-04-27
rsync 2026-04-27/ → NAS ✓ 0m26s (242 files, 325M)
[2026-05-06 19:41:28] Archive DB size: 9.7G
[2026-05-06 19:41:28] Total time: 19m12s
[2026-05-06 19:41:28] Sync complete for 2026-04-27
[2026-05-06 19:41:28] ========================================
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ~/.screenpipe/screenpipe_sync.sh 2026-04-28
[2026-05-06 19:44:49] ========================================
[2026-05-06 19:44:49] Screenpipe sync starting for: 2026-04-28
[2026-05-06 19:44:49] ========================================
[+00m00s] ▶ Preflight checks
Source DB: OK ( 11G)
NAS mount: OK /Volumes/screenpipe
Archive DB: exists (9.7G)
Data dir: OK (223 files, 159M)
[+00m00s] ▶ Counting source rows for 2026-04-28
frames: 4535
elements: 407532
ui_events: 8621
ocr_text: 1623
meetings: 3
[+00m02s] ▶ Initialising tables, indexes, FTS
creating tables ✓ 0m00s
creating indexes ✓ 0m00s
creating FTS tables ✓ 0m00s
[+00m02s] ▶ Syncing data for 2026-04-28
video_chunks ✓ 0m12s
frames (4535 rows) ✓ 1m30s
ocr_text (1623 rows) ✓ 0m32s
ui_events (8621 rows) ✓ 0m01s
elements (407532 rows) ✓ 1m02s
meetings (3 rows) ✓ 0m00s
[+03m19s] ▶ Updating FTS indexes
elements_fts ✓ 1m36s
frames_fts ✓ 2m28s
ui_events_fts ✓ 0m04s
[+07m27s] ▶ Verifying DB
frames: 4535 / 4535 ✓
elements: 407532 / 407532 ✓
ui_events: 8621 / 8621 ✓
ocr_text: 1623 / 1623 ✓
meetings: 3 / 3 ✓
[+08m59s] ▶ Copying data folder for 2026-04-28
rsync 2026-04-28/ → NAS ✓ 0m20s (223 files, 159M)
[2026-05-06 19:54:08] Archive DB size: 10G
[2026-05-06 19:54:08] Total time: 9m19s
[2026-05-06 19:54:08] Sync complete for 2026-04-28
[2026-05-06 19:54:08] ========================================
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ pkill -f screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ rm -rf ~/.screenpipe/
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 92 lukas staff 2944 6 May 20:22 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd .npm
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ ll
total 24
drwx------ 9 lukas staff 288 28 Apr 09:18 .
drwx------+ 92 lukas staff 2944 6 May 20:22 ..
drwx------ 5 lukas staff 160 1 Nov 2021 _cacache
drwx------@ 2 lukas staff 64 28 Apr 09:18 _locks
drwx------ 15 lukas staff 480 27 Apr 19:54 _logs
drwxr-xr-x 67 lukas staff 2144 28 Apr 09:17 _npx
-rw-r--r--@ 1 lukas staff 0 26 Apr 19:10 _update-notifier-last-checked
-rw-r--r-- 1 lukas staff 173 28 Apr 09:18 anonymous-cli-metrics.json
-rw-r--r-- 1 lukas staff 4764 31 Jan 2024 eresolve-report.txt
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ rm -rf ~/.npm/_npx
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ ll
total 52920
drwx------+ 92 lukas staff 2944 6 May 20:22 .
drwxr-xr-x 5 root admin 160 23 Aug 2024 ..
-r-------- 1 lukas staff 7 18 Nov 2021 .CFUserTextEncoding
-rw-r--r--@ 1 lukas staff 28676 27 Apr 09:11 .DS_Store
drwx------+ 10 lukas staff 320 28 Apr 17:07 .Trash
drwx------ 5 lukas staff 160 1 Nov 2021 .aws
-rw-r--r-- 1 lukas staff 341470 29 Sep 2022 .babel.json
-rw-------@ 1 lukas staff 388 25 Jul 2025 .bash_history
-rw-r--r--@ 1 lukas staff 115 18 Apr 13:19 .bashrc
drwxr-xr-x 5 lukas staff 160 11 Mar 2023 .bito
drwx------@ 6 lukas staff 192 9 Apr 19:53 .cache
drwxr-xr-x 20 lukas staff 640 27 Apr 08:58 .claude
-rw------- 1 lukas staff 28647 27 Apr 09:12 .claude.json
drwxr-xr-x@ 20 lukas staff 640 12 Mar 09:12 .codeium
drwxrwxrwx@ 3 lukas staff 96 2 Mar 2023 .composer
drwx------ 16 lukas staff 512 21 May 2025 .config
drwxr-xr-x 15 lukas staff 480 23 Dec 2024 .continue
drwx------@ 3 lukas staff 96 16 Feb 19:13 .copilot
drwxr-xr-x@ 5 lukas staff 160 9 Apr 2025 .cursor
drwxr-xr-x@ 5 lukas staff 160 17 Aug 2024 .cursor-tutor
drwxr-xr-x 3 lukas staff 96 8 Sep 2024 .daytona
drwxr-xr-x@ 4 lukas staff 128 18 Feb 10:52 .devdb
drwx------ 24 lukas staff 768 27 Apr 18:14 .docker
drwx------ 15 lukas staff 480 6 Jun 2023 .dropbox
drwxr-xr-x@ 3 lukas staff 96 20 Nov 2022 .fig.dotfiles.bak
-rw-r--r-- 1 lukas staff 138 5 Mar 2022 .gauth
-rw-r--r-- 1 lukas staff 220 25 Nov 2021 .gitconfig
-rw-r--r-- 1 lukas staff 12288 25 Nov 2021 .gitconfig.swp
drwx------ 5 lukas staff 160 18 Nov 2021 .hammerspoon
drwxr-xr-x 3 lukas staff 96 21 Mar 2025 .idlerc
-rw------- 1 lukas staff 20 28 Apr 16:51 .lesshst
drwx------ 5 lukas staff 160 23 Dec 2024 .local
-rw------- 1 lukas staff 204 16 Mar 2024 .netrc
drwx------ 3 lukas staff 96 1 Nov 2021 .node-gyp
-rw------- 1 lukas staff 4 6 Feb 2024 .node_repl_history
-rw-r--r-- 1 lukas staff 17 24 Dec 2023 .notion-enhancer
drwxr-xr-x 4 lukas staff 128 12 Jul 2024 .notion-py
drwx------ 8 lukas staff 256 6 May 20:24 .npm
-rw------- 1 lukas staff 74 20 May 2024 .npmrc
drwx------ 32 lukas staff 1024 25 Jul 2025 .nvm
drwxr-xr-x 4 lukas staff 128 5 Aug 2023 .postman
-rw-r--r--@ 1 lukas staff 77 9 Feb 2023 .profile
-rw-------@ 1 lukas staff 3153 21 Mar 2025 .python_history
drwx------ 2 lukas staff 64 15 Nov 2021 .quicktype-vscode
drwxr-xr-x@ 8 lukas staff 256 16 Feb 08:48 .redis-insight
drwxr-xr-x 4 lukas staff 128 4 Feb 09:35 .sonarlint
drwx------ 15 lukas staff 480 8 Aug 2025 .ssh
drwxr-xr-x@ 3 lukas staff 96 15 Aug 2025 .streamlit
drwx------ 6 lukas staff 192 17 Oct 2022 .swiftpm
-rw------- 1 lukas staff 12143 27 Apr 14:58 .viminfo
drwx------ 5 lukas staff 160 19 Jun 2023 .vscode
drwxr-xr-x@ 3 lukas staff 96 20 Jan 2025 .warp
UW PICO 5.09 New Buffer
[ Read 1 line ]
^G Get Help ^O WriteOut ^R Read File ^Y Prev Pg ^K Cut Text ^C Cur Pos
^X Exit ^J Justify ^W Where is ^V Next Pg ^U UnCut Text ^T To Spell
drwxr-xr-x 4 lukas staff 128 29 Apr 2023 .wdm
drwxr-xr-x@ 5 lukas staff 160 26 Jan 13:03 .windsurf
drwxr-xr-x 4 lukas staff 128 24 Mar 12:03 .yarn
-rw-r--r-- 1 lukas staff 116 30 Mar 10:12 .yarnrc
-rw-r--r-- 1 lukas staff 49518 21 Apr 09:09 .zcompdump
-rw-r--r--@ 1 lukas staff 46758 2 Nov 2025 .zcompdump.Lukas-Kovaliks-MacBook-Pro-Jiminny.23381
-rw-r--r--@ 1 lukas staff 6116 20 Apr 19:52 .zprofile
-rw-r--r-- 1 lukas staff 1468 8 Apr 2022 .zprofile-copy
-rw-r--r--@ 1 lukas staff 2900 15 Mar 2023 .zprofile.pysave
-rw------- 1 lukas staff 1731 29 Jun 2022 .zprofile.save
-rw-r--r-- 1 lukas staff 1569 8 Apr 2022 .zprofilees
-rw------- 1 lukas staff 50310 28 Apr 11:32 .zsh_history
drwx------ 9 lukas staff 288 6 May 2025 .zsh_sessions
-rw-r--r--@ 1 lukas staff 400 18 Apr 13:19 .zshrc
drwx------@ 9 lukas staff 288 20 Apr 20:55 Applications
drwxr-xr-x@ 2 lukas staff 64 22 Oct 2025 CascadeProjects
drwxr-xr-x 4 lukas staff 128 27 Oct 2025 DEV
drwx------@ 10 lukas staff 320 28 Apr 18:52 Desktop
drwx------@ 7 lukas staff 224 26 Mar 14:40 Documents
drwx------@ 44 lukas staff 1408 24 Apr 16:53 Downloads
drwxr-xr-x@ 4 lukas staff 128 17 Mar 20:27 Keychron_Screen
drwx------@ 112 lukas staff 3584 2 Dec 09:19 Library
drwx------ 7 lukas staff 224 12 Feb 2024 Movies
drwx------+ 5 lukas staff 160 25 Sep 2023 Music
drwx------+ 9 lukas staff 288 25 Sep 2023 Pictures
drwx------ 3 lukas staff 96 8 Nov 2021 Postman
drwx------+ 4 lukas staff 128 28 Oct 2021 Public
-rw-r--r--@ 1 lukas staff 3950 15 Dec 09:16 Untitled 4.spf
drwx------ 4 lukas staff 128 2 Jul 2023 Users
-rw-r--r-- 1 lukas staff 17050804 27 Apr 19:18 cleanshot-live.log
-rw-r--r-- 1 lukas staff 9363061 27 Apr 19:24 cleanshot-screenpipe.log
-rw-r--r-- 1 lukas staff 0 12 Apr 12:50 clip.mp4
-rw-r--r-- 1 lukas staff 0 12 Apr 12:51 frame.jpg
drwx------ 3 lukas staff 96 30 Sep 2022 iCloud Drive (Archive)
drwx------ 16 lukas staff 512 3 Nov 2025 jiminny
drwxr-xr-x 3 lukas staff 96 20 Mar 18:47 node_modules
drwxr-xr-x 4 lukas staff 128 21 Oct 2025 raycast
-rw-r--r-- 1 lukas staff 0 1 Mar 14:26 response.bin
-rwxr-xr-x 1 lukas staff 3824 11 Apr 15:16 screenpipe-day.sh
-rw-r--r-- 1 lukas staff 86 20 Mar 18:47 yarn.lock
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
cd: no such file or directory: /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ touch screenpipe_sync.sh
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ nano screenpipe_sync.sh
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ npx screenpipe@latest record --ignored-windows "Boosteroid" --retention-days 7
detected hardware tier: Mid
warning: parakeet is not supported on this platform, using whisper-tiny instead
2026-05-06T20:27:32.721416Z INFO screenpipe_engine::auth_key: api auth: key resolved via auto-generated
checking permissions...
screen recording: ok
microphone: ok
accessibility: ok
2026-05-06T20:27:32.831033Z INFO screenpipe_screen::monitor::macos_version: Detected macOS version: 14.6
2026-05-06T20:27:34.088403Z INFO screenpipe_engine::sleep_monitor: Starting macOS sleep/wake monitor
2026-05-06T20:27:34.089942Z INFO screenpipe_engine::sleep_monitor: Screen lock/unlock observers registered (CFNotificationCenter)
2026-05-06T20:27:34.090417Z INFO screenpipe_engine::sleep_monitor: Display reconfiguration watcher registered (CGDisplayRegisterReconfigurationCallback)
2026-05-06T20:27:34.112650Z INFO screenpipe_engine::permission_monitor: permission monitor started screen=true mic=true accessibility=true keychain=true
2026-05-06T20:27:34.112711Z INFO screenpipe: meeting detector enabled — independent of transcription mode
2026-05-06T20:27:34.619906Z INFO screenpipe: API server listening on [IP_ADDRESS]:3030 (localhost only)
2026-05-06T20:27:34.619937Z INFO screenpipe: API auth enabled — run `screenpipe auth token` to view your key
2026-05-06T20:27:34.619857Z INFO screenpipe_engine::snapshot_compaction: snapshot compaction worker started (min_age=600s, poll=300s)
2026-05-06T20:27:34.619847Z INFO screenpipe_engine::power::manager: power manager started (poll interval: 10s)
2026-05-06T20:27:34.620018Z INFO screenpipe_engine::vision_manager::manager: Starting VisionManager
2026-05-06T20:27:34.624746Z INFO screenpipe_core::pipes: installed built-in pipe: day-recap
2026-05-06T20:27:34.626304Z INFO screenpipe_core::pipes: installed built-in pipe: standup-update
2026-05-06T20:27:34.628597Z INFO screenpipe_core::pipes: installed built-in pipe: ai-habits
2026-05-06T20:27:34.629463Z INFO screenpipe_core::pipes: installed built-in pipe: time-breakdown
2026-05-06T20:27:34.630081Z INFO screenpipe_core::pipes: installed built-in pipe: video-export
2026-05-06T20:27:34.630972Z INFO screenpipe_core::pipes: installed built-in pipe: meeting-summary
2026-05-06T20:27:34.631427Z INFO screenpipe_core::pipes: loaded pipe: day-recap
2026-05-06T20:27:34.631521Z INFO screenpipe_core::pipes: loaded pipe: standup-update
2026-05-06T20:27:34.631587Z INFO screenpipe_core::pipes: loaded pipe: ai-habits
2026-05-06T20:27:34.631640Z INFO screenpipe_core::pipes: loaded pipe: time-breakdown
2026-05-06T20:27:34.631690Z INFO screenpipe_core::pipes: loaded pipe: video-export
2026-05-06T20:27:34.631738Z INFO screenpipe_core::pipes: loaded pipe: meeting-summary
2026-05-06T20:27:34.631752Z INFO screenpipe_core::pipes: loaded 6 pipes from "/Users/lukas/.screenpipe/pipes"
_
__________________ ___ ____ ____ (_____ ___
/ ___/ ___/ ___/ _ \/ _ \/ __ \ / __ \/ / __ \/ _ \
(__ / /__/ / / __/ __/ / / / / /_/ / / /_/ / __/
/____/\___/_/ \___/\___/_/ /_/ / .___/_/ .___/\___/
/_/ /_/
power AI by everything you've seen, said or heard
open source | runs locally | developer friendly
┌────────────────────────┬────────────────────────────────────┐
│ setting │ value │
├────────────────────────┼────────────────────────────────────┤
│ audio chunk duration │ 30 seconds │
│ port │ 3030 │
│ audio disabled │ false │
│ vision disabled │ false │
│ pause on DRM content │ false │
│ audio engine │ Parakeet │
│ vad engine │ Silero │
│ data directory │ /Users/lukas/.screenpipe │
│ debug mode │ false │
│ telemetry │ true │
│ use pii removal │ true │
│ use all monitors │ true │
│ ignored windows │ ["Boosteroid"] │
│ included windows │ [] │
│ cloud sync │ disabled │
│ auto-destruct pid │ 0 │
│ deepgram key │ not set │
│ api auth │ enabled │
│ encrypt secrets │ disabled │
│ retention days │ 7 │
│ retention mode │ media-only (keep transcripts) │
├────────────────────────┼────────────────────────────────────┤
│ languages │ │
│ │ all languages │
├────────────────────────┼────────────────────────────────────┤
│ monitors │ │
│ │ id: 1 │
│ │ id: 2 │
├────────────────────────┼────────────────────────────────────┤
│ audio devices │ │
│ │ MacBook Pro Microphone (input) │
│ │ System Audio (output) │
└────────────────────────┴────────────────────────────────────┘
you are using local processing. all your data stays on your computer.
warning: telemetry is enabled. only error-level data will be sent.
to disable, use the --disable-telemetry flag.
check latest changes here: https://github.com/screenpipe/screenpipe/releases
2026-05-06T20:27:34.638384Z INFO screenpipe: starting UI event capture
2026-05-06T20:27:34.637679Z INFO screenpipe_core::pipes: pipe scheduler started (generation 2)
2026-05-06T20:27:34.649154Z INFO screenpipe_engine::power::manager: initial power profile: Performance (on_ac=true, battery=Some(94))
2026-05-06T20:27:34.652794Z WARN screenpipe: pi agent install failed: bun not found — install from https://bun.sh
2026-05-06T20:27:34.655839Z INFO screenpipe_engine::ui_recorder: Starting UI event capture
2026-05-06T20:27:34.673877Z INFO screenpipe_engine::ui_recorder: UI recording session started: 54869993-7b4b-491f-b717-2a583517f9c5
2026-05-06T20:27:34.673910Z INFO screenpipe_engine::calendar_speaker_id: speaker identification: started (user_name=<not set>)
2026-05-06T20:27:34.674057Z INFO screenpipe_engine::hot_frame_cache: hot_frame_cache: warming from DB (2026-05-05 17:27:34.674056 UTC to 2026-05-06 17:27:34.674056 UTC)
2026-05-06T20:27:34.674892Z INFO screenpipe_engine::meeting_detector: meeting v2: detection loop started (base_interval=5s, profiles=12)
2026-05-06T20:27:34.675788Z INFO screenpipe_engine::hot_frame_cache: hot_frame_cache: warmed with 0 frame entries, coverage from 2026-05-05 17:27:34.674056 UTC
2026-05-06T20:27:34.686546Z INFO screenpipe_engine::server: Server listening on [IP_ADDRESS]:3030
2026-05-06T20:27:34.691371Z INFO screenpipe_connect::mdns: mdns: advertising screenpipe on port 3030
2026-05-06T20:27:36.270608Z INFO screenpipe_engine::vision_manager::manager: Starting vision recording for monitor 1 (1440x900)
2026-05-06T20:27:36.270669Z INFO screenpipe_engine::vision_manager::manager: Starting event-driven capture for monitor 1 (device: monitor_1)
2026-05-06T20:27:36.270714Z INFO screenpipe_engine::event_driven_capture: event-driven capture started for monitor 1 (device: monitor_1)
2026-05-06T20:27:36.932583Z INFO screenpipe_engine::vision_manager::manager: Starting vision recording for monitor 2 (3008x1253)
2026-05-06T20:27:36.932852Z INFO screenpipe_engine::vision_manager::manager: Starting event-driven capture for monitor 2 (device: monitor_2)
2026-05-06T20:27:36.932882Z INFO screenpipe_engine::vision_manager::manager: VisionManager started with 2/2 monitor(s)
2026-05-06T20:27:36.932899Z INFO screenpipe_engine::vision_manager::monitor_watcher: Starting monitor watcher (event-driven via CGDisplayRegisterReconfigurationCallback, 60s backstop poll)
2026-05-06T20:27:36.932901Z INFO screenpipe_engine::event_driven_capture: event-driven capture started for monitor 2 (device: monitor_2)
2026-05-06T20:27:39.158281Z INFO sck_rs::stream_manager: persistent SCK stream started for display 1 (1440x900, 2fps, 3 excluded)
2026-05-06T20:27:39.593177Z INFO screenpipe_engine::event_driven_capture: startup capture for monitor 1: frame_id=1, dur=101ms
2026-05-06T20:27:40.672366Z INFO sck_rs::stream_manager: persistent SCK stream started for display 2 (3008x1253, 2fps, 3 excluded)
2026-05-06T20:27:41.257664Z INFO screenpipe_engine::event_driven_capture: startup capture for monitor 2: frame_id=2, dur=140ms
2026-05-06T20:27:44.641022Z INFO screenpipe_audio::transcription::engine: whisper model available: "/Users/lukas/.cache/huggingface/hub/models--ggerganov--whisper.cpp/snapshots/5359861c739e955e79d9a303bcbc70fb988958b1/ggml-tiny.bin"
2026-05-06T20:27:44.641079Z INFO screenpipe_audio::transcription::whisper::model: whisper context: gpu acceleration enabled (Metal on macOS, Vulkan on Windows)
2026-05-06T20:27:44.641086Z INFO screenpipe_audio::transcription::engine: loading whisper model with GPU acceleration...
whisper_init_from_file_with_params_no_state: loading model from '/Users/lukas/.cache/huggingface/hub/models--ggerganov--whisper.cpp/snapshots/5359861c739e955e79d9a303bcbc70fb988958b1/ggml-tiny.bin'
whisper_init_with_params_no_state: use gpu = 1
whisper_init_with_params_no_state: flash attn = 0
whisper_init_with_params_no_state: gpu_device = 0
whisper_init_with_params_no_state: dtw = 0
ggml_metal_device_init: tensor API disabled for pre-M5 and pre-A19 devices
ggml_metal_library_init: using embedded metal library
ggml_metal_library_init: loaded in 0.041 sec
ggml_metal_rsets_init: creating a residency set collection (keep_alive = 180 s)
ggml_metal_device_init: GPU name: Apple M1
ggml_metal_device_init: GPU family: MTLGPUFamilyApple7 (1007)
ggml_metal_device_init: GPU family: MTLGPUFamilyCommon3 (3003)
ggml_metal_device_init: GPU family: MTLGPUFamilyMetal3 (5001)
ggml_metal_device_init: simdgroup reduction = true
ggml_metal_device_init: simdgroup matrix mul. = true
ggml_metal_device_init: has unified memory = true
ggml_metal_device_init: has bfloat = true
ggml_metal_device_init: has tensor = false
ggml_metal_device_init: use residency sets = true
ggml_metal_device_init: use shared buffers = true
ggml_metal_device_init: recommendedMaxWorkingSetSize = 11453.25 MB
whisper_init_with_params_no_state: devices = 3
whisper_init_with_params_no_state: backends = 3
whisper_model_load: loading model
whisper_model_load: n_vocab = 51865
whisper_model_load: n_audio_ctx = 1500
whisper_model_load: n_audio_state = 384
whisper_model_load: n_audio_head = 6
whisper_model_load: n_audio_layer = 4
whisper_model_load: n_text_ctx = 448
whisper_model_load: n_text_state = 384
whisper_model_load: n_text_head = 6
whisper_model_load: n_text_layer = 4
whisper_model_load: n_mels = 80
whisper_model_load: ftype = 1
whisper_model_load: qntvr = 0
whisper_model_load: type = 1 (tiny)
whisper_model_load: adding 1608 extra tokens
whisper_model_load: n_langs = 99
whisper_model_load: Metal total size = 77.11 MB
whisper_model_load: model size = 77.11 MB
2026-05-06T20:27:44.857210Z INFO screenpipe_audio::transcription::engine: whisper model loaded successfully
whisper_backend_init_gpu: device 0: Metal (type: 1)
whisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)
whisper_backend_init_gpu: using Metal backend
ggml_metal_init: allocating
ggml_metal_init: found device: Apple M1
ggml_metal_init: picking default device: Apple M1
ggml_metal_init: use fusion = true
ggml_metal_init: use concurrency = true
ggml_metal_init: use graph optimize = true
whisper_backend_init: using BLAS backend
whisper_init_state: kv self size = 3.15 MB
whisper_init_state: kv cross size = 9.44 MB
whisper_init_state: kv pad size = 2.36 MB
whisper_init_state: compute buffer (conv) = 14.17 MB
whisper_init_state: compute buffer (encode) = 65.96 MB
whisper_init_state: compute buffer (cross) = 8.50 MB
whisper_init_state: compute buffer (decode) = 96.83 MB
2026-05-06T20:27:44.861912Z INFO screenpipe_audio::audio_manager::manager: transcription session created (will be reused across segments)
2026-05-06T20:27:44.862480Z INFO screenpipe_audio::audio_manager::manager: audio manager started
2026-05-06T20:27:44.862525Z INFO screenpipe_audio::audio_manager::manager: calendar-assisted speaker diarization: listening for meeting events
2026-05-06T20:27:47.831980Z INFO screenpipe_audio::device::device_manager: starting recording for device: System Audio (output)
2026-05-06T20:27:47.832191Z INFO screenpipe_audio::core::run_record_and_transcribe: starting continuous recording for System Audio (output) (unknown / 30s segments)
2026-05-06T20:27:47.906029Z INFO screenpipe_audio::device::device_manager: starting recording for device: MacBook Pro Microphone (input)
2026-05-06T20:27:47.906090Z INFO screenpipe_audio::core::run_record_and_transcribe: starting continuous recording for MacBook Pro Microphone (input) (wired / 30s segments)
2026-05-06T20:28:15.251258Z INFO screenpipe_engine::event_driven_capture: content dedup: skipping capture for monitor 1 (hash=-8608554010568040663, trigger=visual_change)
whisper_backend_init_gpu: device 0: Metal (type: 1)
whisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)
whisper_backend_init_gpu: using Metal backend
ggml_metal_init: allocating
ggml_metal_init: found device: Apple M1
ggml_metal_init: picking default device: Apple M1
ggml_metal_init: use fusion = true
ggml_metal_init: use concurrency = true
ggml_metal_init: use graph optimize = true
whisper_backend_init: using BLAS backend
whisper_init_state: kv self size = 3.15 MB
whisper_init_state: kv cross size = 9.44 MB
whisper_init_state: kv pad size = 2.36 MB
whisper_init_state: compute buffer (conv) = 14.17 MB
whisper_init_state: compute buffer (encode) = 65.96 MB
whisper_init_state: compute buffer (cross) = 8.50 MB
whisper_init_state: compute buffer (decode) = 96.83 MB
ggml_metal_free: deallocating
whisper_backend_init_gpu: device 0: Metal (type: 1)
whisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)
whisper_backend_init_gpu: using Metal backend
ggml_metal_init: allocating
ggml_metal_init: found device: Apple M1
ggml_metal_init: picking default device: Apple M1
ggml_metal_init: use fusion = true
ggml_metal_init: use concurrency = true
ggml_metal_init: use graph optimize = true
whisper_backend_init: using BLAS backend
whisper_init_state: kv self size = 3.15 MB
whisper_init_state: kv cross size = 9.44 MB
whisper_init_state: kv pad size = 2.36 MB
whisper_init_state: compute buffer (conv) = 14.17 MB
whisper_init_state: compute buffer (encode) = 65.96 MB
whisper_init_state: compute buffer (cross) = 8.50 MB
whisper_init_state: compute buffer (decode) = 96.83 MB
ggml_metal_free: deallocating
whisper_backend_init_gpu: device 0: Metal (type: 1)
whisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)
whisper_backend_init_gpu: using Metal backend
ggml_metal_init: allocating
ggml_metal_init: found device: Apple M1
ggml_metal_init: picking default device: Apple M1
ggml_metal_init: use fusion = true
ggml_metal_init: use concurrency = true
ggml_metal_init: use graph optimize = true
whisper_backend_init: using BLAS backend
whisper_init_state: kv self size = 3.15 MB
whisper_init_state: kv cross size = 9.44 MB
whisper_init_state: kv pad size = 2.36 MB
whisper_init_state: compute buffer (conv) = 14.17 MB
whisper_init_state: compute buffer (encode) = 65.96 MB
whisper_init_state: compute buffer (cross) = 8.50 MB
whisper_init_state: compute buffer (decode) = 96.83 ...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"-rw-r--r-- 1 lukas staff 3298542 28 Apr 18:07 compact_monitor_2_1777388874095.mp4\n-rw-r--r-- 1 lukas staff 2143027 28 Apr 18:13 compact_monitor_2_1777389196097.mp4\n-rw-r--r-- 1 lukas staff 2448311 28 Apr 18:18 compact_monitor_2_1777389532297.mp4\n-rw-r--r-- 1 lukas staff 2780051 28 Apr 18:24 compact_monitor_2_1777389861076.mp4\n-rw-r--r-- 1 lukas staff 2715534 28 Apr 18:29 compact_monitor_2_1777390193677.mp4\n-rw-r--r-- 1 lukas staff 2102173 28 Apr 18:35 compact_monitor_2_1777390515997.mp4\n-rw-r--r-- 1 lukas staff 2324557 28 Apr 18:40 compact_monitor_2_1777390843577.mp4\n-rw-r--r-- 1 lukas staff 1525510 28 Apr 18:46 compact_monitor_2_1777391163945.mp4\n-rw-r--r-- 1 lukas staff 2776584 28 Apr 18:51 compact_monitor_2_1777391495138.mp4\n-rw-r--r-- 1 lukas staff 1168205 28 Apr 18:57 compact_monitor_2_1777391825305.mp4\n-rw-r--r-- 1 lukas staff 1736686 28 Apr 19:02 compact_monitor_2_1777392149583.mp4\n-rw-r--r-- 1 lukas staff 2133415 28 Apr 19:07 compact_monitor_2_1777392471754.mp4\n-rw-r--r-- 1 lukas staff 1289951 28 Apr 19:13 compact_monitor_2_1777392794343.mp4\n-rw-r--r-- 1 lukas staff 223494 28 Apr 19:18 compact_monitor_2_1777393110228.mp4\n-rw-r--r-- 1 lukas staff 222168 28 Apr 19:23 compact_monitor_2_1777393424109.mp4\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-04-28 $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22523176\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 28 Apr 16:51 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11525263360 28 Apr 19:33 db.sqlite\n-rw-r--r-- 1 lukas staff 65536 28 Apr 15:26 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 2323712 28 Apr 22:23 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34227 26 Apr 17:01 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ~/.screenpipe/screenpipe_sync.sh 2026-04-27 \n[2026-05-06 18:58:18] ========================================\n[2026-05-06 18:58:18] Screenpipe sync starting for: 2026-04-27\n[2026-05-06 18:58:18] ========================================\n\n[+00m00s] ▶ Preflight checks\n Source DB: OK ( 11G)\n NAS mount: OK /Volumes/screenpipe\n Archive DB: exists (7.7G)\n Data dir: OK (242 files, 325M)\n\n[+00m04s] ▶ Counting source rows for 2026-04-27\n frames: 7543\n elements: 470235\n ui_events: 9909\n ocr_text: 2193\n meetings: 3\n\n[+00m06s] ▶ Initialising tables, indexes, FTS\n creating tables ✓ 0m00s\n creating indexes ✓ 0m01s\n creating FTS tables ✓ 0m00s\n\n[+00m07s] ▶ Syncing data for 2026-04-27\n video_chunks ✓ 0m11s\n frames (7543 rows) ⠧ Runtime error near line 3: disk I/O error (10)\n frames (7543 rows) ⠴ % \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ~/.screenpipe/screenpipe_sync.sh 2026-04-27\n[2026-05-06 19:22:16] ========================================\n[2026-05-06 19:22:16] Screenpipe sync starting for: 2026-04-27\n[2026-05-06 19:22:16] ========================================\n\n[+00m00s] ▶ Preflight checks\n Source DB: OK ( 11G)\n NAS mount: OK /Volumes/screenpipe\n Archive DB: exists (7.7G)\n Data dir: OK (242 files, 325M)\n\n[+00m01s] ▶ Counting source rows for 2026-04-27\n frames: 7543\n elements: 470235\n ui_events: 9909\n ocr_text: 2193\n meetings: 3\n\n[+00m02s] ▶ Initialising tables, indexes, FTS\n creating tables ✓ 0m00s\n creating indexes ✓ 0m01s\n creating FTS tables ✓ 0m00s\n\n[+00m03s] ▶ Syncing data for 2026-04-27\n video_chunks ✓ 0m11s\n frames (7543 rows) ✓ 4m40s\n ocr_text (2193 rows) ✓ 0m25s\n ui_events (9909 rows) ✓ 0m02s\n elements (470235 rows) ✓ 2m46s\n meetings (3 rows) ✓ 0m00s\n\n[+08m07s] ▶ Updating FTS indexes\n elements_fts ✓ 2m59s\n frames_fts ✓ 6m07s\n ui_events_fts ✓ 0m03s\n\n[+17m16s] ▶ Verifying DB\n frames: 7543 / 7543 ✓\n elements: 470235 / 470235 ✓\n ui_events: 9909 / 9909 ✓\n ocr_text: 2193 / 2193 ✓\n meetings: 3 / 3 ✓\n\n[+18m46s] ▶ Copying data folder for 2026-04-27\n rsync 2026-04-27/ → NAS ✓ 0m26s (242 files, 325M)\n\n[2026-05-06 19:41:28] Archive DB size: 9.7G\n[2026-05-06 19:41:28] Total time: 19m12s\n[2026-05-06 19:41:28] Sync complete for 2026-04-27\n[2026-05-06 19:41:28] ========================================\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ~/.screenpipe/screenpipe_sync.sh 2026-04-28\n[2026-05-06 19:44:49] ========================================\n[2026-05-06 19:44:49] Screenpipe sync starting for: 2026-04-28\n[2026-05-06 19:44:49] ========================================\n\n[+00m00s] ▶ Preflight checks\n Source DB: OK ( 11G)\n NAS mount: OK /Volumes/screenpipe\n Archive DB: exists (9.7G)\n Data dir: OK (223 files, 159M)\n\n[+00m00s] ▶ Counting source rows for 2026-04-28\n frames: 4535\n elements: 407532\n ui_events: 8621\n ocr_text: 1623\n meetings: 3\n\n[+00m02s] ▶ Initialising tables, indexes, FTS\n creating tables ✓ 0m00s\n creating indexes ✓ 0m00s\n creating FTS tables ✓ 0m00s\n\n[+00m02s] ▶ Syncing data for 2026-04-28\n video_chunks ✓ 0m12s\n frames (4535 rows) ✓ 1m30s\n ocr_text (1623 rows) ✓ 0m32s\n ui_events (8621 rows) ✓ 0m01s\n elements (407532 rows) ✓ 1m02s\n meetings (3 rows) ✓ 0m00s\n\n[+03m19s] ▶ Updating FTS indexes\n elements_fts ✓ 1m36s\n frames_fts ✓ 2m28s\n ui_events_fts ✓ 0m04s\n\n[+07m27s] ▶ Verifying DB\n frames: 4535 / 4535 ✓\n elements: 407532 / 407532 ✓\n ui_events: 8621 / 8621 ✓\n ocr_text: 1623 / 1623 ✓\n meetings: 3 / 3 ✓\n\n[+08m59s] ▶ Copying data folder for 2026-04-28\n rsync 2026-04-28/ → NAS ✓ 0m20s (223 files, 159M)\n\n[2026-05-06 19:54:08] Archive DB size: 10G\n[2026-05-06 19:54:08] Total time: 9m19s\n[2026-05-06 19:54:08] Sync complete for 2026-04-28\n[2026-05-06 19:54:08] ========================================\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ pkill -f screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ rm -rf ~/.screenpipe/\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 92 lukas staff 2944 6 May 20:22 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd .npm \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ ll\ntotal 24\ndrwx------ 9 lukas staff 288 28 Apr 09:18 .\ndrwx------+ 92 lukas staff 2944 6 May 20:22 ..\ndrwx------ 5 lukas staff 160 1 Nov 2021 _cacache\ndrwx------@ 2 lukas staff 64 28 Apr 09:18 _locks\ndrwx------ 15 lukas staff 480 27 Apr 19:54 _logs\ndrwxr-xr-x 67 lukas staff 2144 28 Apr 09:17 _npx\n-rw-r--r--@ 1 lukas staff 0 26 Apr 19:10 _update-notifier-last-checked\n-rw-r--r-- 1 lukas staff 173 28 Apr 09:18 anonymous-cli-metrics.json\n-rw-r--r-- 1 lukas staff 4764 31 Jan 2024 eresolve-report.txt\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ rm -rf ~/.npm/_npx\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ ll \ntotal 52920\ndrwx------+ 92 lukas staff 2944 6 May 20:22 .\ndrwxr-xr-x 5 root admin 160 23 Aug 2024 ..\n-r-------- 1 lukas staff 7 18 Nov 2021 .CFUserTextEncoding\n-rw-r--r--@ 1 lukas staff 28676 27 Apr 09:11 .DS_Store\ndrwx------+ 10 lukas staff 320 28 Apr 17:07 .Trash\ndrwx------ 5 lukas staff 160 1 Nov 2021 .aws\n-rw-r--r-- 1 lukas staff 341470 29 Sep 2022 .babel.json\n-rw-------@ 1 lukas staff 388 25 Jul 2025 .bash_history\n-rw-r--r--@ 1 lukas staff 115 18 Apr 13:19 .bashrc\ndrwxr-xr-x 5 lukas staff 160 11 Mar 2023 .bito\ndrwx------@ 6 lukas staff 192 9 Apr 19:53 .cache\ndrwxr-xr-x 20 lukas staff 640 27 Apr 08:58 .claude\n-rw------- 1 lukas staff 28647 27 Apr 09:12 .claude.json\ndrwxr-xr-x@ 20 lukas staff 640 12 Mar 09:12 .codeium\ndrwxrwxrwx@ 3 lukas staff 96 2 Mar 2023 .composer\ndrwx------ 16 lukas staff 512 21 May 2025 .config\ndrwxr-xr-x 15 lukas staff 480 23 Dec 2024 .continue\ndrwx------@ 3 lukas staff 96 16 Feb 19:13 .copilot\ndrwxr-xr-x@ 5 lukas staff 160 9 Apr 2025 .cursor\ndrwxr-xr-x@ 5 lukas staff 160 17 Aug 2024 .cursor-tutor\ndrwxr-xr-x 3 lukas staff 96 8 Sep 2024 .daytona\ndrwxr-xr-x@ 4 lukas staff 128 18 Feb 10:52 .devdb\ndrwx------ 24 lukas staff 768 27 Apr 18:14 .docker\ndrwx------ 15 lukas staff 480 6 Jun 2023 .dropbox\ndrwxr-xr-x@ 3 lukas staff 96 20 Nov 2022 .fig.dotfiles.bak\n-rw-r--r-- 1 lukas staff 138 5 Mar 2022 .gauth\n-rw-r--r-- 1 lukas staff 220 25 Nov 2021 .gitconfig\n-rw-r--r-- 1 lukas staff 12288 25 Nov 2021 .gitconfig.swp\ndrwx------ 5 lukas staff 160 18 Nov 2021 .hammerspoon\ndrwxr-xr-x 3 lukas staff 96 21 Mar 2025 .idlerc\n-rw------- 1 lukas staff 20 28 Apr 16:51 .lesshst\ndrwx------ 5 lukas staff 160 23 Dec 2024 .local\n-rw------- 1 lukas staff 204 16 Mar 2024 .netrc\ndrwx------ 3 lukas staff 96 1 Nov 2021 .node-gyp\n-rw------- 1 lukas staff 4 6 Feb 2024 .node_repl_history\n-rw-r--r-- 1 lukas staff 17 24 Dec 2023 .notion-enhancer\ndrwxr-xr-x 4 lukas staff 128 12 Jul 2024 .notion-py\ndrwx------ 8 lukas staff 256 6 May 20:24 .npm\n-rw------- 1 lukas staff 74 20 May 2024 .npmrc\ndrwx------ 32 lukas staff 1024 25 Jul 2025 .nvm\ndrwxr-xr-x 4 lukas staff 128 5 Aug 2023 .postman\n-rw-r--r--@ 1 lukas staff 77 9 Feb 2023 .profile\n-rw-------@ 1 lukas staff 3153 21 Mar 2025 .python_history\ndrwx------ 2 lukas staff 64 15 Nov 2021 .quicktype-vscode\ndrwxr-xr-x@ 8 lukas staff 256 16 Feb 08:48 .redis-insight\ndrwxr-xr-x 4 lukas staff 128 4 Feb 09:35 .sonarlint\ndrwx------ 15 lukas staff 480 8 Aug 2025 .ssh\ndrwxr-xr-x@ 3 lukas staff 96 15 Aug 2025 .streamlit\ndrwx------ 6 lukas staff 192 17 Oct 2022 .swiftpm\n-rw------- 1 lukas staff 12143 27 Apr 14:58 .viminfo\ndrwx------ 5 lukas staff 160 19 Jun 2023 .vscode\ndrwxr-xr-x@ 3 lukas staff 96 20 Jan 2025 .warp\n UW PICO 5.09 New Buffer \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n [ Read 1 line ] \n^G Get Help ^O WriteOut ^R Read File ^Y Prev Pg ^K Cut Text ^C Cur Pos \n^X Exit ^J Justify ^W Where is ^V Next Pg ^U UnCut Text ^T To Spell \ndrwxr-xr-x 4 lukas staff 128 29 Apr 2023 .wdm\ndrwxr-xr-x@ 5 lukas staff 160 26 Jan 13:03 .windsurf\ndrwxr-xr-x 4 lukas staff 128 24 Mar 12:03 .yarn\n-rw-r--r-- 1 lukas staff 116 30 Mar 10:12 .yarnrc\n-rw-r--r-- 1 lukas staff 49518 21 Apr 09:09 .zcompdump\n-rw-r--r--@ 1 lukas staff 46758 2 Nov 2025 .zcompdump.Lukas-Kovaliks-MacBook-Pro-Jiminny.23381\n-rw-r--r--@ 1 lukas staff 6116 20 Apr 19:52 .zprofile\n-rw-r--r-- 1 lukas staff 1468 8 Apr 2022 .zprofile-copy\n-rw-r--r--@ 1 lukas staff 2900 15 Mar 2023 .zprofile.pysave\n-rw------- 1 lukas staff 1731 29 Jun 2022 .zprofile.save\n-rw-r--r-- 1 lukas staff 1569 8 Apr 2022 .zprofilees\n-rw------- 1 lukas staff 50310 28 Apr 11:32 .zsh_history\ndrwx------ 9 lukas staff 288 6 May 2025 .zsh_sessions\n-rw-r--r--@ 1 lukas staff 400 18 Apr 13:19 .zshrc\ndrwx------@ 9 lukas staff 288 20 Apr 20:55 Applications\ndrwxr-xr-x@ 2 lukas staff 64 22 Oct 2025 CascadeProjects\ndrwxr-xr-x 4 lukas staff 128 27 Oct 2025 DEV\ndrwx------@ 10 lukas staff 320 28 Apr 18:52 Desktop\ndrwx------@ 7 lukas staff 224 26 Mar 14:40 Documents\ndrwx------@ 44 lukas staff 1408 24 Apr 16:53 Downloads\ndrwxr-xr-x@ 4 lukas staff 128 17 Mar 20:27 Keychron_Screen\ndrwx------@ 112 lukas staff 3584 2 Dec 09:19 Library\ndrwx------ 7 lukas staff 224 12 Feb 2024 Movies\ndrwx------+ 5 lukas staff 160 25 Sep 2023 Music\ndrwx------+ 9 lukas staff 288 25 Sep 2023 Pictures\ndrwx------ 3 lukas staff 96 8 Nov 2021 Postman\ndrwx------+ 4 lukas staff 128 28 Oct 2021 Public\n-rw-r--r--@ 1 lukas staff 3950 15 Dec 09:16 Untitled 4.spf\ndrwx------ 4 lukas staff 128 2 Jul 2023 Users\n-rw-r--r-- 1 lukas staff 17050804 27 Apr 19:18 cleanshot-live.log\n-rw-r--r-- 1 lukas staff 9363061 27 Apr 19:24 cleanshot-screenpipe.log\n-rw-r--r-- 1 lukas staff 0 12 Apr 12:50 clip.mp4\n-rw-r--r-- 1 lukas staff 0 12 Apr 12:51 frame.jpg\ndrwx------ 3 lukas staff 96 30 Sep 2022 iCloud Drive (Archive)\ndrwx------ 16 lukas staff 512 3 Nov 2025 jiminny\ndrwxr-xr-x 3 lukas staff 96 20 Mar 18:47 node_modules\ndrwxr-xr-x 4 lukas staff 128 21 Oct 2025 raycast\n-rw-r--r-- 1 lukas staff 0 1 Mar 14:26 response.bin\n-rwxr-xr-x 1 lukas staff 3824 11 Apr 15:16 screenpipe-day.sh\n-rw-r--r-- 1 lukas staff 86 20 Mar 18:47 yarn.lock\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe\ncd: no such file or directory: /Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ touch screenpipe_sync.sh\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ nano screenpipe_sync.sh\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ npx screenpipe@latest record --ignored-windows \"Boosteroid\" --retention-days 7\ndetected hardware tier: Mid\nwarning: parakeet is not supported on this platform, using whisper-tiny instead\n2026-05-06T20:27:32.721416Z INFO screenpipe_engine::auth_key: api auth: key resolved via auto-generated\nchecking permissions...\n screen recording: ok\n microphone: ok\n accessibility: ok\n2026-05-06T20:27:32.831033Z INFO screenpipe_screen::monitor::macos_version: Detected macOS version: 14.6\n2026-05-06T20:27:34.088403Z INFO screenpipe_engine::sleep_monitor: Starting macOS sleep/wake monitor\n2026-05-06T20:27:34.089942Z INFO screenpipe_engine::sleep_monitor: Screen lock/unlock observers registered (CFNotificationCenter)\n2026-05-06T20:27:34.090417Z INFO screenpipe_engine::sleep_monitor: Display reconfiguration watcher registered (CGDisplayRegisterReconfigurationCallback)\n2026-05-06T20:27:34.112650Z INFO screenpipe_engine::permission_monitor: permission monitor started screen=true mic=true accessibility=true keychain=true\n2026-05-06T20:27:34.112711Z INFO screenpipe: meeting detector enabled — independent of transcription mode\n2026-05-06T20:27:34.619906Z INFO screenpipe: API server listening on 127.0.0.1:3030 (localhost only)\n2026-05-06T20:27:34.619937Z INFO screenpipe: API auth enabled — run `screenpipe auth token` to view your key\n2026-05-06T20:27:34.619857Z INFO screenpipe_engine::snapshot_compaction: snapshot compaction worker started (min_age=600s, poll=300s)\n2026-05-06T20:27:34.619847Z INFO screenpipe_engine::power::manager: power manager started (poll interval: 10s)\n2026-05-06T20:27:34.620018Z INFO screenpipe_engine::vision_manager::manager: Starting VisionManager\n2026-05-06T20:27:34.624746Z INFO screenpipe_core::pipes: installed built-in pipe: day-recap\n2026-05-06T20:27:34.626304Z INFO screenpipe_core::pipes: installed built-in pipe: standup-update\n2026-05-06T20:27:34.628597Z INFO screenpipe_core::pipes: installed built-in pipe: ai-habits\n2026-05-06T20:27:34.629463Z INFO screenpipe_core::pipes: installed built-in pipe: time-breakdown\n2026-05-06T20:27:34.630081Z INFO screenpipe_core::pipes: installed built-in pipe: video-export\n2026-05-06T20:27:34.630972Z INFO screenpipe_core::pipes: installed built-in pipe: meeting-summary\n2026-05-06T20:27:34.631427Z INFO screenpipe_core::pipes: loaded pipe: day-recap\n2026-05-06T20:27:34.631521Z INFO screenpipe_core::pipes: loaded pipe: standup-update\n2026-05-06T20:27:34.631587Z INFO screenpipe_core::pipes: loaded pipe: ai-habits\n2026-05-06T20:27:34.631640Z INFO screenpipe_core::pipes: loaded pipe: time-breakdown\n2026-05-06T20:27:34.631690Z INFO screenpipe_core::pipes: loaded pipe: video-export\n2026-05-06T20:27:34.631738Z INFO screenpipe_core::pipes: loaded pipe: meeting-summary\n2026-05-06T20:27:34.631752Z INFO screenpipe_core::pipes: loaded 6 pipes from \"/Users/lukas/.screenpipe/pipes\"\n\n\n\n _ \n __________________ ___ ____ ____ (_____ ___ \n / ___/ ___/ ___/ _ \\/ _ \\/ __ \\ / __ \\/ / __ \\/ _ \\\n (__ / /__/ / / __/ __/ / / / / /_/ / / /_/ / __/\n/____/\\___/_/ \\___/\\___/_/ /_/ / .___/_/ .___/\\___/ \n /_/ /_/ \n\n\n\npower AI by everything you've seen, said or heard\nopen source | runs locally | developer friendly\n\n\n┌────────────────────────┬────────────────────────────────────┐\n│ setting │ value │\n├────────────────────────┼────────────────────────────────────┤\n│ audio chunk duration │ 30 seconds │\n│ port │ 3030 │\n│ audio disabled │ false │\n│ vision disabled │ false │\n│ pause on DRM content │ false │\n│ audio engine │ Parakeet │\n│ vad engine │ Silero │\n│ data directory │ /Users/lukas/.screenpipe │\n│ debug mode │ false │\n│ telemetry │ true │\n│ use pii removal │ true │\n│ use all monitors │ true │\n│ ignored windows │ [\"Boosteroid\"] │\n│ included windows │ [] │\n│ cloud sync │ disabled │\n│ auto-destruct pid │ 0 │\n│ deepgram key │ not set │\n│ api auth │ enabled │\n│ encrypt secrets │ disabled │\n│ retention days │ 7 │\n│ retention mode │ media-only (keep transcripts) │\n├────────────────────────┼────────────────────────────────────┤\n│ languages │ │\n│ │ all languages │\n├────────────────────────┼────────────────────────────────────┤\n│ monitors │ │\n│ │ id: 1 │\n│ │ id: 2 │\n├────────────────────────┼────────────────────────────────────┤\n│ audio devices │ │\n│ │ MacBook Pro Microphone (input) │\n│ │ System Audio (output) │\n└────────────────────────┴────────────────────────────────────┘\nyou are using local processing. all your data stays on your computer.\n\nwarning: telemetry is enabled. only error-level data will be sent.\nto disable, use the --disable-telemetry flag.\n\ncheck latest changes here: https://github.com/screenpipe/screenpipe/releases\n2026-05-06T20:27:34.638384Z INFO screenpipe: starting UI event capture\n2026-05-06T20:27:34.637679Z INFO screenpipe_core::pipes: pipe scheduler started (generation 2)\n2026-05-06T20:27:34.649154Z INFO screenpipe_engine::power::manager: initial power profile: Performance (on_ac=true, battery=Some(94))\n2026-05-06T20:27:34.652794Z WARN screenpipe: pi agent install failed: bun not found — install from https://bun.sh\n2026-05-06T20:27:34.655839Z INFO screenpipe_engine::ui_recorder: Starting UI event capture\n2026-05-06T20:27:34.673877Z INFO screenpipe_engine::ui_recorder: UI recording session started: 54869993-7b4b-491f-b717-2a583517f9c5\n2026-05-06T20:27:34.673910Z INFO screenpipe_engine::calendar_speaker_id: speaker identification: started (user_name=<not set>)\n2026-05-06T20:27:34.674057Z INFO screenpipe_engine::hot_frame_cache: hot_frame_cache: warming from DB (2026-05-05 17:27:34.674056 UTC to 2026-05-06 17:27:34.674056 UTC)\n2026-05-06T20:27:34.674892Z INFO screenpipe_engine::meeting_detector: meeting v2: detection loop started (base_interval=5s, profiles=12)\n2026-05-06T20:27:34.675788Z INFO screenpipe_engine::hot_frame_cache: hot_frame_cache: warmed with 0 frame entries, coverage from 2026-05-05 17:27:34.674056 UTC\n2026-05-06T20:27:34.686546Z INFO screenpipe_engine::server: Server listening on 127.0.0.1:3030\n2026-05-06T20:27:34.691371Z INFO screenpipe_connect::mdns: mdns: advertising screenpipe on port 3030\n2026-05-06T20:27:36.270608Z INFO screenpipe_engine::vision_manager::manager: Starting vision recording for monitor 1 (1440x900)\n2026-05-06T20:27:36.270669Z INFO screenpipe_engine::vision_manager::manager: Starting event-driven capture for monitor 1 (device: monitor_1)\n2026-05-06T20:27:36.270714Z INFO screenpipe_engine::event_driven_capture: event-driven capture started for monitor 1 (device: monitor_1)\n2026-05-06T20:27:36.932583Z INFO screenpipe_engine::vision_manager::manager: Starting vision recording for monitor 2 (3008x1253)\n2026-05-06T20:27:36.932852Z INFO screenpipe_engine::vision_manager::manager: Starting event-driven capture for monitor 2 (device: monitor_2)\n2026-05-06T20:27:36.932882Z INFO screenpipe_engine::vision_manager::manager: VisionManager started with 2/2 monitor(s)\n2026-05-06T20:27:36.932899Z INFO screenpipe_engine::vision_manager::monitor_watcher: Starting monitor watcher (event-driven via CGDisplayRegisterReconfigurationCallback, 60s backstop poll)\n2026-05-06T20:27:36.932901Z INFO screenpipe_engine::event_driven_capture: event-driven capture started for monitor 2 (device: monitor_2)\n2026-05-06T20:27:39.158281Z INFO sck_rs::stream_manager: persistent SCK stream started for display 1 (1440x900, 2fps, 3 excluded)\n2026-05-06T20:27:39.593177Z INFO screenpipe_engine::event_driven_capture: startup capture for monitor 1: frame_id=1, dur=101ms\n2026-05-06T20:27:40.672366Z INFO sck_rs::stream_manager: persistent SCK stream started for display 2 (3008x1253, 2fps, 3 excluded)\n2026-05-06T20:27:41.257664Z INFO screenpipe_engine::event_driven_capture: startup capture for monitor 2: frame_id=2, dur=140ms\n2026-05-06T20:27:44.641022Z INFO screenpipe_audio::transcription::engine: whisper model available: \"/Users/lukas/.cache/huggingface/hub/models--ggerganov--whisper.cpp/snapshots/5359861c739e955e79d9a303bcbc70fb988958b1/ggml-tiny.bin\"\n2026-05-06T20:27:44.641079Z INFO screenpipe_audio::transcription::whisper::model: whisper context: gpu acceleration enabled (Metal on macOS, Vulkan on Windows)\n2026-05-06T20:27:44.641086Z INFO screenpipe_audio::transcription::engine: loading whisper model with GPU acceleration...\nwhisper_init_from_file_with_params_no_state: loading model from '/Users/lukas/.cache/huggingface/hub/models--ggerganov--whisper.cpp/snapshots/5359861c739e955e79d9a303bcbc70fb988958b1/ggml-tiny.bin'\nwhisper_init_with_params_no_state: use gpu = 1\nwhisper_init_with_params_no_state: flash attn = 0\nwhisper_init_with_params_no_state: gpu_device = 0\nwhisper_init_with_params_no_state: dtw = 0\nggml_metal_device_init: tensor API disabled for pre-M5 and pre-A19 devices\nggml_metal_library_init: using embedded metal library\nggml_metal_library_init: loaded in 0.041 sec\nggml_metal_rsets_init: creating a residency set collection (keep_alive = 180 s)\nggml_metal_device_init: GPU name: Apple M1\nggml_metal_device_init: GPU family: MTLGPUFamilyApple7 (1007)\nggml_metal_device_init: GPU family: MTLGPUFamilyCommon3 (3003)\nggml_metal_device_init: GPU family: MTLGPUFamilyMetal3 (5001)\nggml_metal_device_init: simdgroup reduction = true\nggml_metal_device_init: simdgroup matrix mul. = true\nggml_metal_device_init: has unified memory = true\nggml_metal_device_init: has bfloat = true\nggml_metal_device_init: has tensor = false\nggml_metal_device_init: use residency sets = true\nggml_metal_device_init: use shared buffers = true\nggml_metal_device_init: recommendedMaxWorkingSetSize = 11453.25 MB\nwhisper_init_with_params_no_state: devices = 3\nwhisper_init_with_params_no_state: backends = 3\nwhisper_model_load: loading model\nwhisper_model_load: n_vocab = 51865\nwhisper_model_load: n_audio_ctx = 1500\nwhisper_model_load: n_audio_state = 384\nwhisper_model_load: n_audio_head = 6\nwhisper_model_load: n_audio_layer = 4\nwhisper_model_load: n_text_ctx = 448\nwhisper_model_load: n_text_state = 384\nwhisper_model_load: n_text_head = 6\nwhisper_model_load: n_text_layer = 4\nwhisper_model_load: n_mels = 80\nwhisper_model_load: ftype = 1\nwhisper_model_load: qntvr = 0\nwhisper_model_load: type = 1 (tiny)\nwhisper_model_load: adding 1608 extra tokens\nwhisper_model_load: n_langs = 99\nwhisper_model_load: Metal total size = 77.11 MB\nwhisper_model_load: model size = 77.11 MB\n2026-05-06T20:27:44.857210Z INFO screenpipe_audio::transcription::engine: whisper model loaded successfully\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\n2026-05-06T20:27:44.861912Z INFO screenpipe_audio::audio_manager::manager: transcription session created (will be reused across segments)\n2026-05-06T20:27:44.862480Z INFO screenpipe_audio::audio_manager::manager: audio manager started\n2026-05-06T20:27:44.862525Z INFO screenpipe_audio::audio_manager::manager: calendar-assisted speaker diarization: listening for meeting events\n2026-05-06T20:27:47.831980Z INFO screenpipe_audio::device::device_manager: starting recording for device: System Audio (output)\n2026-05-06T20:27:47.832191Z INFO screenpipe_audio::core::run_record_and_transcribe: starting continuous recording for System Audio (output) (unknown / 30s segments)\n2026-05-06T20:27:47.906029Z INFO screenpipe_audio::device::device_manager: starting recording for device: MacBook Pro Microphone (input)\n2026-05-06T20:27:47.906090Z INFO screenpipe_audio::core::run_record_and_transcribe: starting continuous recording for MacBook Pro Microphone (input) (wired / 30s segments)\n2026-05-06T20:28:15.251258Z INFO screenpipe_engine::event_driven_capture: content dedup: skipping capture for monitor 1 (hash=-8608554010568040663, trigger=visual_change)\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\n2026-05-06T20:29:45.187551Z INFO screenpipe_audio::audio_manager::manager: reconciliation: transcribed 6 orphaned chunks\n2026-05-06T20:30:06.916244Z WARN screenpipe_audio::core::source_buffer: [MacBook Pro Microphone (input)] large gap on wired device: 81.4ms elapsed (expected 5.3ms) → inserting 76.0ms silence (7299 samples)\n2026-05-06T20:30:29.881247Z WARN screenpipe_audio::core::source_buffer: [MacBook Pro Microphone (input)] large gap on wired device: 96.0ms elapsed (expected 5.3ms) → inserting 90.7ms silence (8704 samples)\n^C2026-05-06T20:31:44.992913Z INFO screenpipe: received ctrl+c, initiating shutdown\n2026-05-06T20:31:44.993815Z INFO screenpipe_audio::device::device_manager: Stopping device: System Audio (output)\n2026-05-06T20:31:44.993845Z INFO screenpipe_audio::device::device_manager: Stopping device: System Audio (output)\n\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $","depth":4,"on_screen":true,"value":"-rw-r--r-- 1 lukas staff 3298542 28 Apr 18:07 compact_monitor_2_1777388874095.mp4\n-rw-r--r-- 1 lukas staff 2143027 28 Apr 18:13 compact_monitor_2_1777389196097.mp4\n-rw-r--r-- 1 lukas staff 2448311 28 Apr 18:18 compact_monitor_2_1777389532297.mp4\n-rw-r--r-- 1 lukas staff 2780051 28 Apr 18:24 compact_monitor_2_1777389861076.mp4\n-rw-r--r-- 1 lukas staff 2715534 28 Apr 18:29 compact_monitor_2_1777390193677.mp4\n-rw-r--r-- 1 lukas staff 2102173 28 Apr 18:35 compact_monitor_2_1777390515997.mp4\n-rw-r--r-- 1 lukas staff 2324557 28 Apr 18:40 compact_monitor_2_1777390843577.mp4\n-rw-r--r-- 1 lukas staff 1525510 28 Apr 18:46 compact_monitor_2_1777391163945.mp4\n-rw-r--r-- 1 lukas staff 2776584 28 Apr 18:51 compact_monitor_2_1777391495138.mp4\n-rw-r--r-- 1 lukas staff 1168205 28 Apr 18:57 compact_monitor_2_1777391825305.mp4\n-rw-r--r-- 1 lukas staff 1736686 28 Apr 19:02 compact_monitor_2_1777392149583.mp4\n-rw-r--r-- 1 lukas staff 2133415 28 Apr 19:07 compact_monitor_2_1777392471754.mp4\n-rw-r--r-- 1 lukas staff 1289951 28 Apr 19:13 compact_monitor_2_1777392794343.mp4\n-rw-r--r-- 1 lukas staff 223494 28 Apr 19:18 compact_monitor_2_1777393110228.mp4\n-rw-r--r-- 1 lukas staff 222168 28 Apr 19:23 compact_monitor_2_1777393424109.mp4\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-04-28 $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22523176\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 28 Apr 16:51 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11525263360 28 Apr 19:33 db.sqlite\n-rw-r--r-- 1 lukas staff 65536 28 Apr 15:26 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 2323712 28 Apr 22:23 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34227 26 Apr 17:01 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ~/.screenpipe/screenpipe_sync.sh 2026-04-27 \n[2026-05-06 18:58:18] ========================================\n[2026-05-06 18:58:18] Screenpipe sync starting for: 2026-04-27\n[2026-05-06 18:58:18] ========================================\n\n[+00m00s] ▶ Preflight checks\n Source DB: OK ( 11G)\n NAS mount: OK /Volumes/screenpipe\n Archive DB: exists (7.7G)\n Data dir: OK (242 files, 325M)\n\n[+00m04s] ▶ Counting source rows for 2026-04-27\n frames: 7543\n elements: 470235\n ui_events: 9909\n ocr_text: 2193\n meetings: 3\n\n[+00m06s] ▶ Initialising tables, indexes, FTS\n creating tables ✓ 0m00s\n creating indexes ✓ 0m01s\n creating FTS tables ✓ 0m00s\n\n[+00m07s] ▶ Syncing data for 2026-04-27\n video_chunks ✓ 0m11s\n frames (7543 rows) ⠧ Runtime error near line 3: disk I/O error (10)\n frames (7543 rows) ⠴ % \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ~/.screenpipe/screenpipe_sync.sh 2026-04-27\n[2026-05-06 19:22:16] ========================================\n[2026-05-06 19:22:16] Screenpipe sync starting for: 2026-04-27\n[2026-05-06 19:22:16] ========================================\n\n[+00m00s] ▶ Preflight checks\n Source DB: OK ( 11G)\n NAS mount: OK /Volumes/screenpipe\n Archive DB: exists (7.7G)\n Data dir: OK (242 files, 325M)\n\n[+00m01s] ▶ Counting source rows for 2026-04-27\n frames: 7543\n elements: 470235\n ui_events: 9909\n ocr_text: 2193\n meetings: 3\n\n[+00m02s] ▶ Initialising tables, indexes, FTS\n creating tables ✓ 0m00s\n creating indexes ✓ 0m01s\n creating FTS tables ✓ 0m00s\n\n[+00m03s] ▶ Syncing data for 2026-04-27\n video_chunks ✓ 0m11s\n frames (7543 rows) ✓ 4m40s\n ocr_text (2193 rows) ✓ 0m25s\n ui_events (9909 rows) ✓ 0m02s\n elements (470235 rows) ✓ 2m46s\n meetings (3 rows) ✓ 0m00s\n\n[+08m07s] ▶ Updating FTS indexes\n elements_fts ✓ 2m59s\n frames_fts ✓ 6m07s\n ui_events_fts ✓ 0m03s\n\n[+17m16s] ▶ Verifying DB\n frames: 7543 / 7543 ✓\n elements: 470235 / 470235 ✓\n ui_events: 9909 / 9909 ✓\n ocr_text: 2193 / 2193 ✓\n meetings: 3 / 3 ✓\n\n[+18m46s] ▶ Copying data folder for 2026-04-27\n rsync 2026-04-27/ → NAS ✓ 0m26s (242 files, 325M)\n\n[2026-05-06 19:41:28] Archive DB size: 9.7G\n[2026-05-06 19:41:28] Total time: 19m12s\n[2026-05-06 19:41:28] Sync complete for 2026-04-27\n[2026-05-06 19:41:28] ========================================\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ~/.screenpipe/screenpipe_sync.sh 2026-04-28\n[2026-05-06 19:44:49] ========================================\n[2026-05-06 19:44:49] Screenpipe sync starting for: 2026-04-28\n[2026-05-06 19:44:49] ========================================\n\n[+00m00s] ▶ Preflight checks\n Source DB: OK ( 11G)\n NAS mount: OK /Volumes/screenpipe\n Archive DB: exists (9.7G)\n Data dir: OK (223 files, 159M)\n\n[+00m00s] ▶ Counting source rows for 2026-04-28\n frames: 4535\n elements: 407532\n ui_events: 8621\n ocr_text: 1623\n meetings: 3\n\n[+00m02s] ▶ Initialising tables, indexes, FTS\n creating tables ✓ 0m00s\n creating indexes ✓ 0m00s\n creating FTS tables ✓ 0m00s\n\n[+00m02s] ▶ Syncing data for 2026-04-28\n video_chunks ✓ 0m12s\n frames (4535 rows) ✓ 1m30s\n ocr_text (1623 rows) ✓ 0m32s\n ui_events (8621 rows) ✓ 0m01s\n elements (407532 rows) ✓ 1m02s\n meetings (3 rows) ✓ 0m00s\n\n[+03m19s] ▶ Updating FTS indexes\n elements_fts ✓ 1m36s\n frames_fts ✓ 2m28s\n ui_events_fts ✓ 0m04s\n\n[+07m27s] ▶ Verifying DB\n frames: 4535 / 4535 ✓\n elements: 407532 / 407532 ✓\n ui_events: 8621 / 8621 ✓\n ocr_text: 1623 / 1623 ✓\n meetings: 3 / 3 ✓\n\n[+08m59s] ▶ Copying data folder for 2026-04-28\n rsync 2026-04-28/ → NAS ✓ 0m20s (223 files, 159M)\n\n[2026-05-06 19:54:08] Archive DB size: 10G\n[2026-05-06 19:54:08] Total time: 9m19s\n[2026-05-06 19:54:08] Sync complete for 2026-04-28\n[2026-05-06 19:54:08] ========================================\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ pkill -f screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ rm -rf ~/.screenpipe/\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 92 lukas staff 2944 6 May 20:22 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd .npm \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ ll\ntotal 24\ndrwx------ 9 lukas staff 288 28 Apr 09:18 .\ndrwx------+ 92 lukas staff 2944 6 May 20:22 ..\ndrwx------ 5 lukas staff 160 1 Nov 2021 _cacache\ndrwx------@ 2 lukas staff 64 28 Apr 09:18 _locks\ndrwx------ 15 lukas staff 480 27 Apr 19:54 _logs\ndrwxr-xr-x 67 lukas staff 2144 28 Apr 09:17 _npx\n-rw-r--r--@ 1 lukas staff 0 26 Apr 19:10 _update-notifier-last-checked\n-rw-r--r-- 1 lukas staff 173 28 Apr 09:18 anonymous-cli-metrics.json\n-rw-r--r-- 1 lukas staff 4764 31 Jan 2024 eresolve-report.txt\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ rm -rf ~/.npm/_npx\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ ll \ntotal 52920\ndrwx------+ 92 lukas staff 2944 6 May 20:22 .\ndrwxr-xr-x 5 root admin 160 23 Aug 2024 ..\n-r-------- 1 lukas staff 7 18 Nov 2021 .CFUserTextEncoding\n-rw-r--r--@ 1 lukas staff 28676 27 Apr 09:11 .DS_Store\ndrwx------+ 10 lukas staff 320 28 Apr 17:07 .Trash\ndrwx------ 5 lukas staff 160 1 Nov 2021 .aws\n-rw-r--r-- 1 lukas staff 341470 29 Sep 2022 .babel.json\n-rw-------@ 1 lukas staff 388 25 Jul 2025 .bash_history\n-rw-r--r--@ 1 lukas staff 115 18 Apr 13:19 .bashrc\ndrwxr-xr-x 5 lukas staff 160 11 Mar 2023 .bito\ndrwx------@ 6 lukas staff 192 9 Apr 19:53 .cache\ndrwxr-xr-x 20 lukas staff 640 27 Apr 08:58 .claude\n-rw------- 1 lukas staff 28647 27 Apr 09:12 .claude.json\ndrwxr-xr-x@ 20 lukas staff 640 12 Mar 09:12 .codeium\ndrwxrwxrwx@ 3 lukas staff 96 2 Mar 2023 .composer\ndrwx------ 16 lukas staff 512 21 May 2025 .config\ndrwxr-xr-x 15 lukas staff 480 23 Dec 2024 .continue\ndrwx------@ 3 lukas staff 96 16 Feb 19:13 .copilot\ndrwxr-xr-x@ 5 lukas staff 160 9 Apr 2025 .cursor\ndrwxr-xr-x@ 5 lukas staff 160 17 Aug 2024 .cursor-tutor\ndrwxr-xr-x 3 lukas staff 96 8 Sep 2024 .daytona\ndrwxr-xr-x@ 4 lukas staff 128 18 Feb 10:52 .devdb\ndrwx------ 24 lukas staff 768 27 Apr 18:14 .docker\ndrwx------ 15 lukas staff 480 6 Jun 2023 .dropbox\ndrwxr-xr-x@ 3 lukas staff 96 20 Nov 2022 .fig.dotfiles.bak\n-rw-r--r-- 1 lukas staff 138 5 Mar 2022 .gauth\n-rw-r--r-- 1 lukas staff 220 25 Nov 2021 .gitconfig\n-rw-r--r-- 1 lukas staff 12288 25 Nov 2021 .gitconfig.swp\ndrwx------ 5 lukas staff 160 18 Nov 2021 .hammerspoon\ndrwxr-xr-x 3 lukas staff 96 21 Mar 2025 .idlerc\n-rw------- 1 lukas staff 20 28 Apr 16:51 .lesshst\ndrwx------ 5 lukas staff 160 23 Dec 2024 .local\n-rw------- 1 lukas staff 204 16 Mar 2024 .netrc\ndrwx------ 3 lukas staff 96 1 Nov 2021 .node-gyp\n-rw------- 1 lukas staff 4 6 Feb 2024 .node_repl_history\n-rw-r--r-- 1 lukas staff 17 24 Dec 2023 .notion-enhancer\ndrwxr-xr-x 4 lukas staff 128 12 Jul 2024 .notion-py\ndrwx------ 8 lukas staff 256 6 May 20:24 .npm\n-rw------- 1 lukas staff 74 20 May 2024 .npmrc\ndrwx------ 32 lukas staff 1024 25 Jul 2025 .nvm\ndrwxr-xr-x 4 lukas staff 128 5 Aug 2023 .postman\n-rw-r--r--@ 1 lukas staff 77 9 Feb 2023 .profile\n-rw-------@ 1 lukas staff 3153 21 Mar 2025 .python_history\ndrwx------ 2 lukas staff 64 15 Nov 2021 .quicktype-vscode\ndrwxr-xr-x@ 8 lukas staff 256 16 Feb 08:48 .redis-insight\ndrwxr-xr-x 4 lukas staff 128 4 Feb 09:35 .sonarlint\ndrwx------ 15 lukas staff 480 8 Aug 2025 .ssh\ndrwxr-xr-x@ 3 lukas staff 96 15 Aug 2025 .streamlit\ndrwx------ 6 lukas staff 192 17 Oct 2022 .swiftpm\n-rw------- 1 lukas staff 12143 27 Apr 14:58 .viminfo\ndrwx------ 5 lukas staff 160 19 Jun 2023 .vscode\ndrwxr-xr-x@ 3 lukas staff 96 20 Jan 2025 .warp\n UW PICO 5.09 New Buffer \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n [ Read 1 line ] \n^G Get Help ^O WriteOut ^R Read File ^Y Prev Pg ^K Cut Text ^C Cur Pos \n^X Exit ^J Justify ^W Where is ^V Next Pg ^U UnCut Text ^T To Spell \ndrwxr-xr-x 4 lukas staff 128 29 Apr 2023 .wdm\ndrwxr-xr-x@ 5 lukas staff 160 26 Jan 13:03 .windsurf\ndrwxr-xr-x 4 lukas staff 128 24 Mar 12:03 .yarn\n-rw-r--r-- 1 lukas staff 116 30 Mar 10:12 .yarnrc\n-rw-r--r-- 1 lukas staff 49518 21 Apr 09:09 .zcompdump\n-rw-r--r--@ 1 lukas staff 46758 2 Nov 2025 .zcompdump.Lukas-Kovaliks-MacBook-Pro-Jiminny.23381\n-rw-r--r--@ 1 lukas staff 6116 20 Apr 19:52 .zprofile\n-rw-r--r-- 1 lukas staff 1468 8 Apr 2022 .zprofile-copy\n-rw-r--r--@ 1 lukas staff 2900 15 Mar 2023 .zprofile.pysave\n-rw------- 1 lukas staff 1731 29 Jun 2022 .zprofile.save\n-rw-r--r-- 1 lukas staff 1569 8 Apr 2022 .zprofilees\n-rw------- 1 lukas staff 50310 28 Apr 11:32 .zsh_history\ndrwx------ 9 lukas staff 288 6 May 2025 .zsh_sessions\n-rw-r--r--@ 1 lukas staff 400 18 Apr 13:19 .zshrc\ndrwx------@ 9 lukas staff 288 20 Apr 20:55 Applications\ndrwxr-xr-x@ 2 lukas staff 64 22 Oct 2025 CascadeProjects\ndrwxr-xr-x 4 lukas staff 128 27 Oct 2025 DEV\ndrwx------@ 10 lukas staff 320 28 Apr 18:52 Desktop\ndrwx------@ 7 lukas staff 224 26 Mar 14:40 Documents\ndrwx------@ 44 lukas staff 1408 24 Apr 16:53 Downloads\ndrwxr-xr-x@ 4 lukas staff 128 17 Mar 20:27 Keychron_Screen\ndrwx------@ 112 lukas staff 3584 2 Dec 09:19 Library\ndrwx------ 7 lukas staff 224 12 Feb 2024 Movies\ndrwx------+ 5 lukas staff 160 25 Sep 2023 Music\ndrwx------+ 9 lukas staff 288 25 Sep 2023 Pictures\ndrwx------ 3 lukas staff 96 8 Nov 2021 Postman\ndrwx------+ 4 lukas staff 128 28 Oct 2021 Public\n-rw-r--r--@ 1 lukas staff 3950 15 Dec 09:16 Untitled 4.spf\ndrwx------ 4 lukas staff 128 2 Jul 2023 Users\n-rw-r--r-- 1 lukas staff 17050804 27 Apr 19:18 cleanshot-live.log\n-rw-r--r-- 1 lukas staff 9363061 27 Apr 19:24 cleanshot-screenpipe.log\n-rw-r--r-- 1 lukas staff 0 12 Apr 12:50 clip.mp4\n-rw-r--r-- 1 lukas staff 0 12 Apr 12:51 frame.jpg\ndrwx------ 3 lukas staff 96 30 Sep 2022 iCloud Drive (Archive)\ndrwx------ 16 lukas staff 512 3 Nov 2025 jiminny\ndrwxr-xr-x 3 lukas staff 96 20 Mar 18:47 node_modules\ndrwxr-xr-x 4 lukas staff 128 21 Oct 2025 raycast\n-rw-r--r-- 1 lukas staff 0 1 Mar 14:26 response.bin\n-rwxr-xr-x 1 lukas staff 3824 11 Apr 15:16 screenpipe-day.sh\n-rw-r--r-- 1 lukas staff 86 20 Mar 18:47 yarn.lock\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe\ncd: no such file or directory: /Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ touch screenpipe_sync.sh\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ nano screenpipe_sync.sh\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ npx screenpipe@latest record --ignored-windows \"Boosteroid\" --retention-days 7\ndetected hardware tier: Mid\nwarning: parakeet is not supported on this platform, using whisper-tiny instead\n2026-05-06T20:27:32.721416Z INFO screenpipe_engine::auth_key: api auth: key resolved via auto-generated\nchecking permissions...\n screen recording: ok\n microphone: ok\n accessibility: ok\n2026-05-06T20:27:32.831033Z INFO screenpipe_screen::monitor::macos_version: Detected macOS version: 14.6\n2026-05-06T20:27:34.088403Z INFO screenpipe_engine::sleep_monitor: Starting macOS sleep/wake monitor\n2026-05-06T20:27:34.089942Z INFO screenpipe_engine::sleep_monitor: Screen lock/unlock observers registered (CFNotificationCenter)\n2026-05-06T20:27:34.090417Z INFO screenpipe_engine::sleep_monitor: Display reconfiguration watcher registered (CGDisplayRegisterReconfigurationCallback)\n2026-05-06T20:27:34.112650Z INFO screenpipe_engine::permission_monitor: permission monitor started screen=true mic=true accessibility=true keychain=true\n2026-05-06T20:27:34.112711Z INFO screenpipe: meeting detector enabled — independent of transcription mode\n2026-05-06T20:27:34.619906Z INFO screenpipe: API server listening on 127.0.0.1:3030 (localhost only)\n2026-05-06T20:27:34.619937Z INFO screenpipe: API auth enabled — run `screenpipe auth token` to view your key\n2026-05-06T20:27:34.619857Z INFO screenpipe_engine::snapshot_compaction: snapshot compaction worker started (min_age=600s, poll=300s)\n2026-05-06T20:27:34.619847Z INFO screenpipe_engine::power::manager: power manager started (poll interval: 10s)\n2026-05-06T20:27:34.620018Z INFO screenpipe_engine::vision_manager::manager: Starting VisionManager\n2026-05-06T20:27:34.624746Z INFO screenpipe_core::pipes: installed built-in pipe: day-recap\n2026-05-06T20:27:34.626304Z INFO screenpipe_core::pipes: installed built-in pipe: standup-update\n2026-05-06T20:27:34.628597Z INFO screenpipe_core::pipes: installed built-in pipe: ai-habits\n2026-05-06T20:27:34.629463Z INFO screenpipe_core::pipes: installed built-in pipe: time-breakdown\n2026-05-06T20:27:34.630081Z INFO screenpipe_core::pipes: installed built-in pipe: video-export\n2026-05-06T20:27:34.630972Z INFO screenpipe_core::pipes: installed built-in pipe: meeting-summary\n2026-05-06T20:27:34.631427Z INFO screenpipe_core::pipes: loaded pipe: day-recap\n2026-05-06T20:27:34.631521Z INFO screenpipe_core::pipes: loaded pipe: standup-update\n2026-05-06T20:27:34.631587Z INFO screenpipe_core::pipes: loaded pipe: ai-habits\n2026-05-06T20:27:34.631640Z INFO screenpipe_core::pipes: loaded pipe: time-breakdown\n2026-05-06T20:27:34.631690Z INFO screenpipe_core::pipes: loaded pipe: video-export\n2026-05-06T20:27:34.631738Z INFO screenpipe_core::pipes: loaded pipe: meeting-summary\n2026-05-06T20:27:34.631752Z INFO screenpipe_core::pipes: loaded 6 pipes from \"/Users/lukas/.screenpipe/pipes\"\n\n\n\n _ \n __________________ ___ ____ ____ (_____ ___ \n / ___/ ___/ ___/ _ \\/ _ \\/ __ \\ / __ \\/ / __ \\/ _ \\\n (__ / /__/ / / __/ __/ / / / / /_/ / / /_/ / __/\n/____/\\___/_/ \\___/\\___/_/ /_/ / .___/_/ .___/\\___/ \n /_/ /_/ \n\n\n\npower AI by everything you've seen, said or heard\nopen source | runs locally | developer friendly\n\n\n┌────────────────────────┬────────────────────────────────────┐\n│ setting │ value │\n├────────────────────────┼────────────────────────────────────┤\n│ audio chunk duration │ 30 seconds │\n│ port │ 3030 │\n│ audio disabled │ false │\n│ vision disabled │ false │\n│ pause on DRM content │ false │\n│ audio engine │ Parakeet │\n│ vad engine │ Silero │\n│ data directory │ /Users/lukas/.screenpipe │\n│ debug mode │ false │\n│ telemetry │ true │\n│ use pii removal │ true │\n│ use all monitors │ true │\n│ ignored windows │ [\"Boosteroid\"] │\n│ included windows │ [] │\n│ cloud sync │ disabled │\n│ auto-destruct pid │ 0 │\n│ deepgram key │ not set │\n│ api auth │ enabled │\n│ encrypt secrets │ disabled │\n│ retention days │ 7 │\n│ retention mode │ media-only (keep transcripts) │\n├────────────────────────┼────────────────────────────────────┤\n│ languages │ │\n│ │ all languages │\n├────────────────────────┼────────────────────────────────────┤\n│ monitors │ │\n│ │ id: 1 │\n│ │ id: 2 │\n├────────────────────────┼────────────────────────────────────┤\n│ audio devices │ │\n│ │ MacBook Pro Microphone (input) │\n│ │ System Audio (output) │\n└────────────────────────┴────────────────────────────────────┘\nyou are using local processing. all your data stays on your computer.\n\nwarning: telemetry is enabled. only error-level data will be sent.\nto disable, use the --disable-telemetry flag.\n\ncheck latest changes here: https://github.com/screenpipe/screenpipe/releases\n2026-05-06T20:27:34.638384Z INFO screenpipe: starting UI event capture\n2026-05-06T20:27:34.637679Z INFO screenpipe_core::pipes: pipe scheduler started (generation 2)\n2026-05-06T20:27:34.649154Z INFO screenpipe_engine::power::manager: initial power profile: Performance (on_ac=true, battery=Some(94))\n2026-05-06T20:27:34.652794Z WARN screenpipe: pi agent install failed: bun not found — install from https://bun.sh\n2026-05-06T20:27:34.655839Z INFO screenpipe_engine::ui_recorder: Starting UI event capture\n2026-05-06T20:27:34.673877Z INFO screenpipe_engine::ui_recorder: UI recording session started: 54869993-7b4b-491f-b717-2a583517f9c5\n2026-05-06T20:27:34.673910Z INFO screenpipe_engine::calendar_speaker_id: speaker identification: started (user_name=<not set>)\n2026-05-06T20:27:34.674057Z INFO screenpipe_engine::hot_frame_cache: hot_frame_cache: warming from DB (2026-05-05 17:27:34.674056 UTC to 2026-05-06 17:27:34.674056 UTC)\n2026-05-06T20:27:34.674892Z INFO screenpipe_engine::meeting_detector: meeting v2: detection loop started (base_interval=5s, profiles=12)\n2026-05-06T20:27:34.675788Z INFO screenpipe_engine::hot_frame_cache: hot_frame_cache: warmed with 0 frame entries, coverage from 2026-05-05 17:27:34.674056 UTC\n2026-05-06T20:27:34.686546Z INFO screenpipe_engine::server: Server listening on 127.0.0.1:3030\n2026-05-06T20:27:34.691371Z INFO screenpipe_connect::mdns: mdns: advertising screenpipe on port 3030\n2026-05-06T20:27:36.270608Z INFO screenpipe_engine::vision_manager::manager: Starting vision recording for monitor 1 (1440x900)\n2026-05-06T20:27:36.270669Z INFO screenpipe_engine::vision_manager::manager: Starting event-driven capture for monitor 1 (device: monitor_1)\n2026-05-06T20:27:36.270714Z INFO screenpipe_engine::event_driven_capture: event-driven capture started for monitor 1 (device: monitor_1)\n2026-05-06T20:27:36.932583Z INFO screenpipe_engine::vision_manager::manager: Starting vision recording for monitor 2 (3008x1253)\n2026-05-06T20:27:36.932852Z INFO screenpipe_engine::vision_manager::manager: Starting event-driven capture for monitor 2 (device: monitor_2)\n2026-05-06T20:27:36.932882Z INFO screenpipe_engine::vision_manager::manager: VisionManager started with 2/2 monitor(s)\n2026-05-06T20:27:36.932899Z INFO screenpipe_engine::vision_manager::monitor_watcher: Starting monitor watcher (event-driven via CGDisplayRegisterReconfigurationCallback, 60s backstop poll)\n2026-05-06T20:27:36.932901Z INFO screenpipe_engine::event_driven_capture: event-driven capture started for monitor 2 (device: monitor_2)\n2026-05-06T20:27:39.158281Z INFO sck_rs::stream_manager: persistent SCK stream started for display 1 (1440x900, 2fps, 3 excluded)\n2026-05-06T20:27:39.593177Z INFO screenpipe_engine::event_driven_capture: startup capture for monitor 1: frame_id=1, dur=101ms\n2026-05-06T20:27:40.672366Z INFO sck_rs::stream_manager: persistent SCK stream started for display 2 (3008x1253, 2fps, 3 excluded)\n2026-05-06T20:27:41.257664Z INFO screenpipe_engine::event_driven_capture: startup capture for monitor 2: frame_id=2, dur=140ms\n2026-05-06T20:27:44.641022Z INFO screenpipe_audio::transcription::engine: whisper model available: \"/Users/lukas/.cache/huggingface/hub/models--ggerganov--whisper.cpp/snapshots/5359861c739e955e79d9a303bcbc70fb988958b1/ggml-tiny.bin\"\n2026-05-06T20:27:44.641079Z INFO screenpipe_audio::transcription::whisper::model: whisper context: gpu acceleration enabled (Metal on macOS, Vulkan on Windows)\n2026-05-06T20:27:44.641086Z INFO screenpipe_audio::transcription::engine: loading whisper model with GPU acceleration...\nwhisper_init_from_file_with_params_no_state: loading model from '/Users/lukas/.cache/huggingface/hub/models--ggerganov--whisper.cpp/snapshots/5359861c739e955e79d9a303bcbc70fb988958b1/ggml-tiny.bin'\nwhisper_init_with_params_no_state: use gpu = 1\nwhisper_init_with_params_no_state: flash attn = 0\nwhisper_init_with_params_no_state: gpu_device = 0\nwhisper_init_with_params_no_state: dtw = 0\nggml_metal_device_init: tensor API disabled for pre-M5 and pre-A19 devices\nggml_metal_library_init: using embedded metal library\nggml_metal_library_init: loaded in 0.041 sec\nggml_metal_rsets_init: creating a residency set collection (keep_alive = 180 s)\nggml_metal_device_init: GPU name: Apple M1\nggml_metal_device_init: GPU family: MTLGPUFamilyApple7 (1007)\nggml_metal_device_init: GPU family: MTLGPUFamilyCommon3 (3003)\nggml_metal_device_init: GPU family: MTLGPUFamilyMetal3 (5001)\nggml_metal_device_init: simdgroup reduction = true\nggml_metal_device_init: simdgroup matrix mul. = true\nggml_metal_device_init: has unified memory = true\nggml_metal_device_init: has bfloat = true\nggml_metal_device_init: has tensor = false\nggml_metal_device_init: use residency sets = true\nggml_metal_device_init: use shared buffers = true\nggml_metal_device_init: recommendedMaxWorkingSetSize = 11453.25 MB\nwhisper_init_with_params_no_state: devices = 3\nwhisper_init_with_params_no_state: backends = 3\nwhisper_model_load: loading model\nwhisper_model_load: n_vocab = 51865\nwhisper_model_load: n_audio_ctx = 1500\nwhisper_model_load: n_audio_state = 384\nwhisper_model_load: n_audio_head = 6\nwhisper_model_load: n_audio_layer = 4\nwhisper_model_load: n_text_ctx = 448\nwhisper_model_load: n_text_state = 384\nwhisper_model_load: n_text_head = 6\nwhisper_model_load: n_text_layer = 4\nwhisper_model_load: n_mels = 80\nwhisper_model_load: ftype = 1\nwhisper_model_load: qntvr = 0\nwhisper_model_load: type = 1 (tiny)\nwhisper_model_load: adding 1608 extra tokens\nwhisper_model_load: n_langs = 99\nwhisper_model_load: Metal total size = 77.11 MB\nwhisper_model_load: model size = 77.11 MB\n2026-05-06T20:27:44.857210Z INFO screenpipe_audio::transcription::engine: whisper model loaded successfully\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\n2026-05-06T20:27:44.861912Z INFO screenpipe_audio::audio_manager::manager: transcription session created (will be reused across segments)\n2026-05-06T20:27:44.862480Z INFO screenpipe_audio::audio_manager::manager: audio manager started\n2026-05-06T20:27:44.862525Z INFO screenpipe_audio::audio_manager::manager: calendar-assisted speaker diarization: listening for meeting events\n2026-05-06T20:27:47.831980Z INFO screenpipe_audio::device::device_manager: starting recording for device: System Audio (output)\n2026-05-06T20:27:47.832191Z INFO screenpipe_audio::core::run_record_and_transcribe: starting continuous recording for System Audio (output) (unknown / 30s segments)\n2026-05-06T20:27:47.906029Z INFO screenpipe_audio::device::device_manager: starting recording for device: MacBook Pro Microphone (input)\n2026-05-06T20:27:47.906090Z INFO screenpipe_audio::core::run_record_and_transcribe: starting continuous recording for MacBook Pro Microphone (input) (wired / 30s segments)\n2026-05-06T20:28:15.251258Z INFO screenpipe_engine::event_driven_capture: content dedup: skipping capture for monitor 1 (hash=-8608554010568040663, trigger=visual_change)\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\n2026-05-06T20:29:45.187551Z INFO screenpipe_audio::audio_manager::manager: reconciliation: transcribed 6 orphaned chunks\n2026-05-06T20:30:06.916244Z WARN screenpipe_audio::core::source_buffer: [MacBook Pro Microphone (input)] large gap on wired device: 81.4ms elapsed (expected 5.3ms) → inserting 76.0ms silence (7299 samples)\n2026-05-06T20:30:29.881247Z WARN screenpipe_audio::core::source_buffer: [MacBook Pro Microphone (input)] large gap on wired device: 96.0ms elapsed (expected 5.3ms) → inserting 90.7ms silence (8704 samples)\n^C2026-05-06T20:31:44.992913Z INFO screenpipe: received ctrl+c, initiating shutdown\n2026-05-06T20:31:44.993815Z INFO screenpipe_audio::device::device_manager: Stopping device: System Audio (output)\n2026-05-06T20:31:44.993845Z INFO screenpipe_audio::device::device_manager: Stopping device: System Audio (output)\n\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $","is_focused":true},{"role":"AXTextField","text":"you","depth":3,"bounds":{"left":0.7888889,"top":0.10555556,"width":0.13055556,"height":0.024444444},"on_screen":true,"automation_id":"_NS:65","value":"you","role_description":"search text field","subrole":"AXSearchField","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"search","depth":4,"bounds":{"left":0.7902778,"top":0.10555556,"width":0.017361112,"height":0.024444444},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"cancel","depth":4,"bounds":{"left":0.9013889,"top":0.10555556,"width":0.015277778,"height":0.024444444},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"go left","depth":3,"bounds":{"left":0.925,"top":0.10666667,"width":0.014583333,"height":0.023333333},"on_screen":true,"automation_id":"_NS:59","role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"go right","depth":3,"bounds":{"left":0.93958336,"top":0.10666667,"width":0.014583333,"height":0.023333333},"on_screen":true,"automation_id":"_NS:49","role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXRadioButton","text":"DOCKER","depth":2,"bounds":{"left":0.0,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.004166667,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"DEV (docker)","depth":2,"bounds":{"left":0.16388889,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.16805555,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"APP (-zsh)","depth":2,"bounds":{"left":0.32777777,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.33194444,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.49166667,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.49583334,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"screenpipe\"","depth":2,"bounds":{"left":0.65555555,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.6597222,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.8194444,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.82361114,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"⌥⌘1","depth":1,"bounds":{"left":0.9548611,"top":0.032222223,"width":0.03888889,"height":0.018888889},"on_screen":true,"automation_id":"_NS:8","role_description":"text"},{"role":"AXStaticText","text":"screenpipe\"","depth":1,"bounds":{"left":0.47083333,"top":0.033333335,"width":0.058333334,"height":0.017777778},"on_screen":true,"role_description":"text"}]...
|
-6269591095506064108
|
3182944612367924321
|
visual_change
|
accessibility
|
NULL
|
-rw-r--r-- 1 lukas staff 3298542 28 Apr 18:07 -rw-r--r-- 1 lukas staff 3298542 28 Apr 18:07 compact_monitor_2_1777388874095.mp4
-rw-r--r-- 1 lukas staff 2143027 28 Apr 18:13 compact_monitor_2_1777389196097.mp4
-rw-r--r-- 1 lukas staff 2448311 28 Apr 18:18 compact_monitor_2_1777389532297.mp4
-rw-r--r-- 1 lukas staff 2780051 28 Apr 18:24 compact_monitor_2_1777389861076.mp4
-rw-r--r-- 1 lukas staff 2715534 28 Apr 18:29 compact_monitor_2_1777390193677.mp4
-rw-r--r-- 1 lukas staff 2102173 28 Apr 18:35 compact_monitor_2_1777390515997.mp4
-rw-r--r-- 1 lukas staff 2324557 28 Apr 18:40 compact_monitor_2_1777390843577.mp4
-rw-r--r-- 1 lukas staff 1525510 28 Apr 18:46 compact_monitor_2_1777391163945.mp4
-rw-r--r-- 1 lukas staff 2776584 28 Apr 18:51 compact_monitor_2_1777391495138.mp4
-rw-r--r-- 1 lukas staff 1168205 28 Apr 18:57 compact_monitor_2_1777391825305.mp4
-rw-r--r-- 1 lukas staff 1736686 28 Apr 19:02 compact_monitor_2_1777392149583.mp4
-rw-r--r-- 1 lukas staff 2133415 28 Apr 19:07 compact_monitor_2_1777392471754.mp4
-rw-r--r-- 1 lukas staff 1289951 28 Apr 19:13 compact_monitor_2_1777392794343.mp4
-rw-r--r-- 1 lukas staff 223494 28 Apr 19:18 compact_monitor_2_1777393110228.mp4
-rw-r--r-- 1 lukas staff 222168 28 Apr 19:23 compact_monitor_2_1777393424109.mp4
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-04-28 $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22523176
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 28 Apr 16:51 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11525263360 28 Apr 19:33 db.sqlite
-rw-r--r-- 1 lukas staff 65536 28 Apr 15:26 db.sqlite-shm
-rw-r--r-- 1 lukas staff 2323712 28 Apr 22:23 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34227 26 Apr 17:01 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ~/.screenpipe/screenpipe_sync.sh 2026-04-27
[2026-05-06 18:58:18] ========================================
[2026-05-06 18:58:18] Screenpipe sync starting for: 2026-04-27
[2026-05-06 18:58:18] ========================================
[+00m00s] ▶ Preflight checks
Source DB: OK ( 11G)
NAS mount: OK /Volumes/screenpipe
Archive DB: exists (7.7G)
Data dir: OK (242 files, 325M)
[+00m04s] ▶ Counting source rows for 2026-04-27
frames: 7543
elements: 470235
ui_events: 9909
ocr_text: 2193
meetings: 3
[+00m06s] ▶ Initialising tables, indexes, FTS
creating tables ✓ 0m00s
creating indexes ✓ 0m01s
creating FTS tables ✓ 0m00s
[+00m07s] ▶ Syncing data for 2026-04-27
video_chunks ✓ 0m11s
frames (7543 rows) ⠧ Runtime error near line 3: disk I/O error (10)
frames (7543 rows) ⠴ %
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ~/.screenpipe/screenpipe_sync.sh 2026-04-27
[2026-05-06 19:22:16] ========================================
[2026-05-06 19:22:16] Screenpipe sync starting for: 2026-04-27
[2026-05-06 19:22:16] ========================================
[+00m00s] ▶ Preflight checks
Source DB: OK ( 11G)
NAS mount: OK /Volumes/screenpipe
Archive DB: exists (7.7G)
Data dir: OK (242 files, 325M)
[+00m01s] ▶ Counting source rows for 2026-04-27
frames: 7543
elements: 470235
ui_events: 9909
ocr_text: 2193
meetings: 3
[+00m02s] ▶ Initialising tables, indexes, FTS
creating tables ✓ 0m00s
creating indexes ✓ 0m01s
creating FTS tables ✓ 0m00s
[+00m03s] ▶ Syncing data for 2026-04-27
video_chunks ✓ 0m11s
frames (7543 rows) ✓ 4m40s
ocr_text (2193 rows) ✓ 0m25s
ui_events (9909 rows) ✓ 0m02s
elements (470235 rows) ✓ 2m46s
meetings (3 rows) ✓ 0m00s
[+08m07s] ▶ Updating FTS indexes
elements_fts ✓ 2m59s
frames_fts ✓ 6m07s
ui_events_fts ✓ 0m03s
[+17m16s] ▶ Verifying DB
frames: 7543 / 7543 ✓
elements: 470235 / 470235 ✓
ui_events: 9909 / 9909 ✓
ocr_text: 2193 / 2193 ✓
meetings: 3 / 3 ✓
[+18m46s] ▶ Copying data folder for 2026-04-27
rsync 2026-04-27/ → NAS ✓ 0m26s (242 files, 325M)
[2026-05-06 19:41:28] Archive DB size: 9.7G
[2026-05-06 19:41:28] Total time: 19m12s
[2026-05-06 19:41:28] Sync complete for 2026-04-27
[2026-05-06 19:41:28] ========================================
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ~/.screenpipe/screenpipe_sync.sh 2026-04-28
[2026-05-06 19:44:49] ========================================
[2026-05-06 19:44:49] Screenpipe sync starting for: 2026-04-28
[2026-05-06 19:44:49] ========================================
[+00m00s] ▶ Preflight checks
Source DB: OK ( 11G)
NAS mount: OK /Volumes/screenpipe
Archive DB: exists (9.7G)
Data dir: OK (223 files, 159M)
[+00m00s] ▶ Counting source rows for 2026-04-28
frames: 4535
elements: 407532
ui_events: 8621
ocr_text: 1623
meetings: 3
[+00m02s] ▶ Initialising tables, indexes, FTS
creating tables ✓ 0m00s
creating indexes ✓ 0m00s
creating FTS tables ✓ 0m00s
[+00m02s] ▶ Syncing data for 2026-04-28
video_chunks ✓ 0m12s
frames (4535 rows) ✓ 1m30s
ocr_text (1623 rows) ✓ 0m32s
ui_events (8621 rows) ✓ 0m01s
elements (407532 rows) ✓ 1m02s
meetings (3 rows) ✓ 0m00s
[+03m19s] ▶ Updating FTS indexes
elements_fts ✓ 1m36s
frames_fts ✓ 2m28s
ui_events_fts ✓ 0m04s
[+07m27s] ▶ Verifying DB
frames: 4535 / 4535 ✓
elements: 407532 / 407532 ✓
ui_events: 8621 / 8621 ✓
ocr_text: 1623 / 1623 ✓
meetings: 3 / 3 ✓
[+08m59s] ▶ Copying data folder for 2026-04-28
rsync 2026-04-28/ → NAS ✓ 0m20s (223 files, 159M)
[2026-05-06 19:54:08] Archive DB size: 10G
[2026-05-06 19:54:08] Total time: 9m19s
[2026-05-06 19:54:08] Sync complete for 2026-04-28
[2026-05-06 19:54:08] ========================================
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ pkill -f screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ rm -rf ~/.screenpipe/
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 92 lukas staff 2944 6 May 20:22 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd .npm
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ ll
total 24
drwx------ 9 lukas staff 288 28 Apr 09:18 .
drwx------+ 92 lukas staff 2944 6 May 20:22 ..
drwx------ 5 lukas staff 160 1 Nov 2021 _cacache
drwx------@ 2 lukas staff 64 28 Apr 09:18 _locks
drwx------ 15 lukas staff 480 27 Apr 19:54 _logs
drwxr-xr-x 67 lukas staff 2144 28 Apr 09:17 _npx
-rw-r--r--@ 1 lukas staff 0 26 Apr 19:10 _update-notifier-last-checked
-rw-r--r-- 1 lukas staff 173 28 Apr 09:18 anonymous-cli-metrics.json
-rw-r--r-- 1 lukas staff 4764 31 Jan 2024 eresolve-report.txt
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ rm -rf ~/.npm/_npx
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ ll
total 52920
drwx------+ 92 lukas staff 2944 6 May 20:22 .
drwxr-xr-x 5 root admin 160 23 Aug 2024 ..
-r-------- 1 lukas staff 7 18 Nov 2021 .CFUserTextEncoding
-rw-r--r--@ 1 lukas staff 28676 27 Apr 09:11 .DS_Store
drwx------+ 10 lukas staff 320 28 Apr 17:07 .Trash
drwx------ 5 lukas staff 160 1 Nov 2021 .aws
-rw-r--r-- 1 lukas staff 341470 29 Sep 2022 .babel.json
-rw-------@ 1 lukas staff 388 25 Jul 2025 .bash_history
-rw-r--r--@ 1 lukas staff 115 18 Apr 13:19 .bashrc
drwxr-xr-x 5 lukas staff 160 11 Mar 2023 .bito
drwx------@ 6 lukas staff 192 9 Apr 19:53 .cache
drwxr-xr-x 20 lukas staff 640 27 Apr 08:58 .claude
-rw------- 1 lukas staff 28647 27 Apr 09:12 .claude.json
drwxr-xr-x@ 20 lukas staff 640 12 Mar 09:12 .codeium
drwxrwxrwx@ 3 lukas staff 96 2 Mar 2023 .composer
drwx------ 16 lukas staff 512 21 May 2025 .config
drwxr-xr-x 15 lukas staff 480 23 Dec 2024 .continue
drwx------@ 3 lukas staff 96 16 Feb 19:13 .copilot
drwxr-xr-x@ 5 lukas staff 160 9 Apr 2025 .cursor
drwxr-xr-x@ 5 lukas staff 160 17 Aug 2024 .cursor-tutor
drwxr-xr-x 3 lukas staff 96 8 Sep 2024 .daytona
drwxr-xr-x@ 4 lukas staff 128 18 Feb 10:52 .devdb
drwx------ 24 lukas staff 768 27 Apr 18:14 .docker
drwx------ 15 lukas staff 480 6 Jun 2023 .dropbox
drwxr-xr-x@ 3 lukas staff 96 20 Nov 2022 .fig.dotfiles.bak
-rw-r--r-- 1 lukas staff 138 5 Mar 2022 .gauth
-rw-r--r-- 1 lukas staff 220 25 Nov 2021 .gitconfig
-rw-r--r-- 1 lukas staff 12288 25 Nov 2021 .gitconfig.swp
drwx------ 5 lukas staff 160 18 Nov 2021 .hammerspoon
drwxr-xr-x 3 lukas staff 96 21 Mar 2025 .idlerc
-rw------- 1 lukas staff 20 28 Apr 16:51 .lesshst
drwx------ 5 lukas staff 160 23 Dec 2024 .local
-rw------- 1 lukas staff 204 16 Mar 2024 .netrc
drwx------ 3 lukas staff 96 1 Nov 2021 .node-gyp
-rw------- 1 lukas staff 4 6 Feb 2024 .node_repl_history
-rw-r--r-- 1 lukas staff 17 24 Dec 2023 .notion-enhancer
drwxr-xr-x 4 lukas staff 128 12 Jul 2024 .notion-py
drwx------ 8 lukas staff 256 6 May 20:24 .npm
-rw------- 1 lukas staff 74 20 May 2024 .npmrc
drwx------ 32 lukas staff 1024 25 Jul 2025 .nvm
drwxr-xr-x 4 lukas staff 128 5 Aug 2023 .postman
-rw-r--r--@ 1 lukas staff 77 9 Feb 2023 .profile
-rw-------@ 1 lukas staff 3153 21 Mar 2025 .python_history
drwx------ 2 lukas staff 64 15 Nov 2021 .quicktype-vscode
drwxr-xr-x@ 8 lukas staff 256 16 Feb 08:48 .redis-insight
drwxr-xr-x 4 lukas staff 128 4 Feb 09:35 .sonarlint
drwx------ 15 lukas staff 480 8 Aug 2025 .ssh
drwxr-xr-x@ 3 lukas staff 96 15 Aug 2025 .streamlit
drwx------ 6 lukas staff 192 17 Oct 2022 .swiftpm
-rw------- 1 lukas staff 12143 27 Apr 14:58 .viminfo
drwx------ 5 lukas staff 160 19 Jun 2023 .vscode
drwxr-xr-x@ 3 lukas staff 96 20 Jan 2025 .warp
UW PICO 5.09 New Buffer
[ Read 1 line ]
^G Get Help ^O WriteOut ^R Read File ^Y Prev Pg ^K Cut Text ^C Cur Pos
^X Exit ^J Justify ^W Where is ^V Next Pg ^U UnCut Text ^T To Spell
drwxr-xr-x 4 lukas staff 128 29 Apr 2023 .wdm
drwxr-xr-x@ 5 lukas staff 160 26 Jan 13:03 .windsurf
drwxr-xr-x 4 lukas staff 128 24 Mar 12:03 .yarn
-rw-r--r-- 1 lukas staff 116 30 Mar 10:12 .yarnrc
-rw-r--r-- 1 lukas staff 49518 21 Apr 09:09 .zcompdump
-rw-r--r--@ 1 lukas staff 46758 2 Nov 2025 .zcompdump.Lukas-Kovaliks-MacBook-Pro-Jiminny.23381
-rw-r--r--@ 1 lukas staff 6116 20 Apr 19:52 .zprofile
-rw-r--r-- 1 lukas staff 1468 8 Apr 2022 .zprofile-copy
-rw-r--r--@ 1 lukas staff 2900 15 Mar 2023 .zprofile.pysave
-rw------- 1 lukas staff 1731 29 Jun 2022 .zprofile.save
-rw-r--r-- 1 lukas staff 1569 8 Apr 2022 .zprofilees
-rw------- 1 lukas staff 50310 28 Apr 11:32 .zsh_history
drwx------ 9 lukas staff 288 6 May 2025 .zsh_sessions
-rw-r--r--@ 1 lukas staff 400 18 Apr 13:19 .zshrc
drwx------@ 9 lukas staff 288 20 Apr 20:55 Applications
drwxr-xr-x@ 2 lukas staff 64 22 Oct 2025 CascadeProjects
drwxr-xr-x 4 lukas staff 128 27 Oct 2025 DEV
drwx------@ 10 lukas staff 320 28 Apr 18:52 Desktop
drwx------@ 7 lukas staff 224 26 Mar 14:40 Documents
drwx------@ 44 lukas staff 1408 24 Apr 16:53 Downloads
drwxr-xr-x@ 4 lukas staff 128 17 Mar 20:27 Keychron_Screen
drwx------@ 112 lukas staff 3584 2 Dec 09:19 Library
drwx------ 7 lukas staff 224 12 Feb 2024 Movies
drwx------+ 5 lukas staff 160 25 Sep 2023 Music
drwx------+ 9 lukas staff 288 25 Sep 2023 Pictures
drwx------ 3 lukas staff 96 8 Nov 2021 Postman
drwx------+ 4 lukas staff 128 28 Oct 2021 Public
-rw-r--r--@ 1 lukas staff 3950 15 Dec 09:16 Untitled 4.spf
drwx------ 4 lukas staff 128 2 Jul 2023 Users
-rw-r--r-- 1 lukas staff 17050804 27 Apr 19:18 cleanshot-live.log
-rw-r--r-- 1 lukas staff 9363061 27 Apr 19:24 cleanshot-screenpipe.log
-rw-r--r-- 1 lukas staff 0 12 Apr 12:50 clip.mp4
-rw-r--r-- 1 lukas staff 0 12 Apr 12:51 frame.jpg
drwx------ 3 lukas staff 96 30 Sep 2022 iCloud Drive (Archive)
drwx------ 16 lukas staff 512 3 Nov 2025 jiminny
drwxr-xr-x 3 lukas staff 96 20 Mar 18:47 node_modules
drwxr-xr-x 4 lukas staff 128 21 Oct 2025 raycast
-rw-r--r-- 1 lukas staff 0 1 Mar 14:26 response.bin
-rwxr-xr-x 1 lukas staff 3824 11 Apr 15:16 screenpipe-day.sh
-rw-r--r-- 1 lukas staff 86 20 Mar 18:47 yarn.lock
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
cd: no such file or directory: /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ touch screenpipe_sync.sh
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ nano screenpipe_sync.sh
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ npx screenpipe@latest record --ignored-windows "Boosteroid" --retention-days 7
detected hardware tier: Mid
warning: parakeet is not supported on this platform, using whisper-tiny instead
2026-05-06T20:27:32.721416Z INFO screenpipe_engine::auth_key: api auth: key resolved via auto-generated
checking permissions...
screen recording: ok
microphone: ok
accessibility: ok
2026-05-06T20:27:32.831033Z INFO screenpipe_screen::monitor::macos_version: Detected macOS version: 14.6
2026-05-06T20:27:34.088403Z INFO screenpipe_engine::sleep_monitor: Starting macOS sleep/wake monitor
2026-05-06T20:27:34.089942Z INFO screenpipe_engine::sleep_monitor: Screen lock/unlock observers registered (CFNotificationCenter)
2026-05-06T20:27:34.090417Z INFO screenpipe_engine::sleep_monitor: Display reconfiguration watcher registered (CGDisplayRegisterReconfigurationCallback)
2026-05-06T20:27:34.112650Z INFO screenpipe_engine::permission_monitor: permission monitor started screen=true mic=true accessibility=true keychain=true
2026-05-06T20:27:34.112711Z INFO screenpipe: meeting detector enabled — independent of transcription mode
2026-05-06T20:27:34.619906Z INFO screenpipe: API server listening on [IP_ADDRESS]:3030 (localhost only)
2026-05-06T20:27:34.619937Z INFO screenpipe: API auth enabled — run `screenpipe auth token` to view your key
2026-05-06T20:27:34.619857Z INFO screenpipe_engine::snapshot_compaction: snapshot compaction worker started (min_age=600s, poll=300s)
2026-05-06T20:27:34.619847Z INFO screenpipe_engine::power::manager: power manager started (poll interval: 10s)
2026-05-06T20:27:34.620018Z INFO screenpipe_engine::vision_manager::manager: Starting VisionManager
2026-05-06T20:27:34.624746Z INFO screenpipe_core::pipes: installed built-in pipe: day-recap
2026-05-06T20:27:34.626304Z INFO screenpipe_core::pipes: installed built-in pipe: standup-update
2026-05-06T20:27:34.628597Z INFO screenpipe_core::pipes: installed built-in pipe: ai-habits
2026-05-06T20:27:34.629463Z INFO screenpipe_core::pipes: installed built-in pipe: time-breakdown
2026-05-06T20:27:34.630081Z INFO screenpipe_core::pipes: installed built-in pipe: video-export
2026-05-06T20:27:34.630972Z INFO screenpipe_core::pipes: installed built-in pipe: meeting-summary
2026-05-06T20:27:34.631427Z INFO screenpipe_core::pipes: loaded pipe: day-recap
2026-05-06T20:27:34.631521Z INFO screenpipe_core::pipes: loaded pipe: standup-update
2026-05-06T20:27:34.631587Z INFO screenpipe_core::pipes: loaded pipe: ai-habits
2026-05-06T20:27:34.631640Z INFO screenpipe_core::pipes: loaded pipe: time-breakdown
2026-05-06T20:27:34.631690Z INFO screenpipe_core::pipes: loaded pipe: video-export
2026-05-06T20:27:34.631738Z INFO screenpipe_core::pipes: loaded pipe: meeting-summary
2026-05-06T20:27:34.631752Z INFO screenpipe_core::pipes: loaded 6 pipes from "/Users/lukas/.screenpipe/pipes"
_
__________________ ___ ____ ____ (_____ ___
/ ___/ ___/ ___/ _ \/ _ \/ __ \ / __ \/ / __ \/ _ \
(__ / /__/ / / __/ __/ / / / / /_/ / / /_/ / __/
/____/\___/_/ \___/\___/_/ /_/ / .___/_/ .___/\___/
/_/ /_/
power AI by everything you've seen, said or heard
open source | runs locally | developer friendly
┌────────────────────────┬────────────────────────────────────┐
│ setting │ value │
├────────────────────────┼────────────────────────────────────┤
│ audio chunk duration │ 30 seconds │
│ port │ 3030 │
│ audio disabled │ false │
│ vision disabled │ false │
│ pause on DRM content │ false │
│ audio engine │ Parakeet │
│ vad engine │ Silero │
│ data directory │ /Users/lukas/.screenpipe │
│ debug mode │ false │
│ telemetry │ true │
│ use pii removal │ true │
│ use all monitors │ true │
│ ignored windows │ ["Boosteroid"] │
│ included windows │ [] │
│ cloud sync │ disabled │
│ auto-destruct pid │ 0 │
│ deepgram key │ not set │
│ api auth │ enabled │
│ encrypt secrets │ disabled │
│ retention days │ 7 │
│ retention mode │ media-only (keep transcripts) │
├────────────────────────┼────────────────────────────────────┤
│ languages │ │
│ │ all languages │
├────────────────────────┼────────────────────────────────────┤
│ monitors │ │
│ │ id: 1 │
│ │ id: 2 │
├────────────────────────┼────────────────────────────────────┤
│ audio devices │ │
│ │ MacBook Pro Microphone (input) │
│ │ System Audio (output) │
└────────────────────────┴────────────────────────────────────┘
you are using local processing. all your data stays on your computer.
warning: telemetry is enabled. only error-level data will be sent.
to disable, use the --disable-telemetry flag.
check latest changes here: https://github.com/screenpipe/screenpipe/releases
2026-05-06T20:27:34.638384Z INFO screenpipe: starting UI event capture
2026-05-06T20:27:34.637679Z INFO screenpipe_core::pipes: pipe scheduler started (generation 2)
2026-05-06T20:27:34.649154Z INFO screenpipe_engine::power::manager: initial power profile: Performance (on_ac=true, battery=Some(94))
2026-05-06T20:27:34.652794Z WARN screenpipe: pi agent install failed: bun not found — install from https://bun.sh
2026-05-06T20:27:34.655839Z INFO screenpipe_engine::ui_recorder: Starting UI event capture
2026-05-06T20:27:34.673877Z INFO screenpipe_engine::ui_recorder: UI recording session started: 54869993-7b4b-491f-b717-2a583517f9c5
2026-05-06T20:27:34.673910Z INFO screenpipe_engine::calendar_speaker_id: speaker identification: started (user_name=<not set>)
2026-05-06T20:27:34.674057Z INFO screenpipe_engine::hot_frame_cache: hot_frame_cache: warming from DB (2026-05-05 17:27:34.674056 UTC to 2026-05-06 17:27:34.674056 UTC)
2026-05-06T20:27:34.674892Z INFO screenpipe_engine::meeting_detector: meeting v2: detection loop started (base_interval=5s, profiles=12)
2026-05-06T20:27:34.675788Z INFO screenpipe_engine::hot_frame_cache: hot_frame_cache: warmed with 0 frame entries, coverage from 2026-05-05 17:27:34.674056 UTC
2026-05-06T20:27:34.686546Z INFO screenpipe_engine::server: Server listening on [IP_ADDRESS]:3030
2026-05-06T20:27:34.691371Z INFO screenpipe_connect::mdns: mdns: advertising screenpipe on port 3030
2026-05-06T20:27:36.270608Z INFO screenpipe_engine::vision_manager::manager: Starting vision recording for monitor 1 (1440x900)
2026-05-06T20:27:36.270669Z INFO screenpipe_engine::vision_manager::manager: Starting event-driven capture for monitor 1 (device: monitor_1)
2026-05-06T20:27:36.270714Z INFO screenpipe_engine::event_driven_capture: event-driven capture started for monitor 1 (device: monitor_1)
2026-05-06T20:27:36.932583Z INFO screenpipe_engine::vision_manager::manager: Starting vision recording for monitor 2 (3008x1253)
2026-05-06T20:27:36.932852Z INFO screenpipe_engine::vision_manager::manager: Starting event-driven capture for monitor 2 (device: monitor_2)
2026-05-06T20:27:36.932882Z INFO screenpipe_engine::vision_manager::manager: VisionManager started with 2/2 monitor(s)
2026-05-06T20:27:36.932899Z INFO screenpipe_engine::vision_manager::monitor_watcher: Starting monitor watcher (event-driven via CGDisplayRegisterReconfigurationCallback, 60s backstop poll)
2026-05-06T20:27:36.932901Z INFO screenpipe_engine::event_driven_capture: event-driven capture started for monitor 2 (device: monitor_2)
2026-05-06T20:27:39.158281Z INFO sck_rs::stream_manager: persistent SCK stream started for display 1 (1440x900, 2fps, 3 excluded)
2026-05-06T20:27:39.593177Z INFO screenpipe_engine::event_driven_capture: startup capture for monitor 1: frame_id=1, dur=101ms
2026-05-06T20:27:40.672366Z INFO sck_rs::stream_manager: persistent SCK stream started for display 2 (3008x1253, 2fps, 3 excluded)
2026-05-06T20:27:41.257664Z INFO screenpipe_engine::event_driven_capture: startup capture for monitor 2: frame_id=2, dur=140ms
2026-05-06T20:27:44.641022Z INFO screenpipe_audio::transcription::engine: whisper model available: "/Users/lukas/.cache/huggingface/hub/models--ggerganov--whisper.cpp/snapshots/5359861c739e955e79d9a303bcbc70fb988958b1/ggml-tiny.bin"
2026-05-06T20:27:44.641079Z INFO screenpipe_audio::transcription::whisper::model: whisper context: gpu acceleration enabled (Metal on macOS, Vulkan on Windows)
2026-05-06T20:27:44.641086Z INFO screenpipe_audio::transcription::engine: loading whisper model with GPU acceleration...
whisper_init_from_file_with_params_no_state: loading model from '/Users/lukas/.cache/huggingface/hub/models--ggerganov--whisper.cpp/snapshots/5359861c739e955e79d9a303bcbc70fb988958b1/ggml-tiny.bin'
whisper_init_with_params_no_state: use gpu = 1
whisper_init_with_params_no_state: flash attn = 0
whisper_init_with_params_no_state: gpu_device = 0
whisper_init_with_params_no_state: dtw = 0
ggml_metal_device_init: tensor API disabled for pre-M5 and pre-A19 devices
ggml_metal_library_init: using embedded metal library
ggml_metal_library_init: loaded in 0.041 sec
ggml_metal_rsets_init: creating a residency set collection (keep_alive = 180 s)
ggml_metal_device_init: GPU name: Apple M1
ggml_metal_device_init: GPU family: MTLGPUFamilyApple7 (1007)
ggml_metal_device_init: GPU family: MTLGPUFamilyCommon3 (3003)
ggml_metal_device_init: GPU family: MTLGPUFamilyMetal3 (5001)
ggml_metal_device_init: simdgroup reduction = true
ggml_metal_device_init: simdgroup matrix mul. = true
ggml_metal_device_init: has unified memory = true
ggml_metal_device_init: has bfloat = true
ggml_metal_device_init: has tensor = false
ggml_metal_device_init: use residency sets = true
ggml_metal_device_init: use shared buffers = true
ggml_metal_device_init: recommendedMaxWorkingSetSize = 11453.25 MB
whisper_init_with_params_no_state: devices = 3
whisper_init_with_params_no_state: backends = 3
whisper_model_load: loading model
whisper_model_load: n_vocab = 51865
whisper_model_load: n_audio_ctx = 1500
whisper_model_load: n_audio_state = 384
whisper_model_load: n_audio_head = 6
whisper_model_load: n_audio_layer = 4
whisper_model_load: n_text_ctx = 448
whisper_model_load: n_text_state = 384
whisper_model_load: n_text_head = 6
whisper_model_load: n_text_layer = 4
whisper_model_load: n_mels = 80
whisper_model_load: ftype = 1
whisper_model_load: qntvr = 0
whisper_model_load: type = 1 (tiny)
whisper_model_load: adding 1608 extra tokens
whisper_model_load: n_langs = 99
whisper_model_load: Metal total size = 77.11 MB
whisper_model_load: model size = 77.11 MB
2026-05-06T20:27:44.857210Z INFO screenpipe_audio::transcription::engine: whisper model loaded successfully
whisper_backend_init_gpu: device 0: Metal (type: 1)
whisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)
whisper_backend_init_gpu: using Metal backend
ggml_metal_init: allocating
ggml_metal_init: found device: Apple M1
ggml_metal_init: picking default device: Apple M1
ggml_metal_init: use fusion = true
ggml_metal_init: use concurrency = true
ggml_metal_init: use graph optimize = true
whisper_backend_init: using BLAS backend
whisper_init_state: kv self size = 3.15 MB
whisper_init_state: kv cross size = 9.44 MB
whisper_init_state: kv pad size = 2.36 MB
whisper_init_state: compute buffer (conv) = 14.17 MB
whisper_init_state: compute buffer (encode) = 65.96 MB
whisper_init_state: compute buffer (cross) = 8.50 MB
whisper_init_state: compute buffer (decode) = 96.83 MB
2026-05-06T20:27:44.861912Z INFO screenpipe_audio::audio_manager::manager: transcription session created (will be reused across segments)
2026-05-06T20:27:44.862480Z INFO screenpipe_audio::audio_manager::manager: audio manager started
2026-05-06T20:27:44.862525Z INFO screenpipe_audio::audio_manager::manager: calendar-assisted speaker diarization: listening for meeting events
2026-05-06T20:27:47.831980Z INFO screenpipe_audio::device::device_manager: starting recording for device: System Audio (output)
2026-05-06T20:27:47.832191Z INFO screenpipe_audio::core::run_record_and_transcribe: starting continuous recording for System Audio (output) (unknown / 30s segments)
2026-05-06T20:27:47.906029Z INFO screenpipe_audio::device::device_manager: starting recording for device: MacBook Pro Microphone (input)
2026-05-06T20:27:47.906090Z INFO screenpipe_audio::core::run_record_and_transcribe: starting continuous recording for MacBook Pro Microphone (input) (wired / 30s segments)
2026-05-06T20:28:15.251258Z INFO screenpipe_engine::event_driven_capture: content dedup: skipping capture for monitor 1 (hash=-8608554010568040663, trigger=visual_change)
whisper_backend_init_gpu: device 0: Metal (type: 1)
whisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)
whisper_backend_init_gpu: using Metal backend
ggml_metal_init: allocating
ggml_metal_init: found device: Apple M1
ggml_metal_init: picking default device: Apple M1
ggml_metal_init: use fusion = true
ggml_metal_init: use concurrency = true
ggml_metal_init: use graph optimize = true
whisper_backend_init: using BLAS backend
whisper_init_state: kv self size = 3.15 MB
whisper_init_state: kv cross size = 9.44 MB
whisper_init_state: kv pad size = 2.36 MB
whisper_init_state: compute buffer (conv) = 14.17 MB
whisper_init_state: compute buffer (encode) = 65.96 MB
whisper_init_state: compute buffer (cross) = 8.50 MB
whisper_init_state: compute buffer (decode) = 96.83 MB
ggml_metal_free: deallocating
whisper_backend_init_gpu: device 0: Metal (type: 1)
whisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)
whisper_backend_init_gpu: using Metal backend
ggml_metal_init: allocating
ggml_metal_init: found device: Apple M1
ggml_metal_init: picking default device: Apple M1
ggml_metal_init: use fusion = true
ggml_metal_init: use concurrency = true
ggml_metal_init: use graph optimize = true
whisper_backend_init: using BLAS backend
whisper_init_state: kv self size = 3.15 MB
whisper_init_state: kv cross size = 9.44 MB
whisper_init_state: kv pad size = 2.36 MB
whisper_init_state: compute buffer (conv) = 14.17 MB
whisper_init_state: compute buffer (encode) = 65.96 MB
whisper_init_state: compute buffer (cross) = 8.50 MB
whisper_init_state: compute buffer (decode) = 96.83 MB
ggml_metal_free: deallocating
whisper_backend_init_gpu: device 0: Metal (type: 1)
whisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)
whisper_backend_init_gpu: using Metal backend
ggml_metal_init: allocating
ggml_metal_init: found device: Apple M1
ggml_metal_init: picking default device: Apple M1
ggml_metal_init: use fusion = true
ggml_metal_init: use concurrency = true
ggml_metal_init: use graph optimize = true
whisper_backend_init: using BLAS backend
whisper_init_state: kv self size = 3.15 MB
whisper_init_state: kv cross size = 9.44 MB
whisper_init_state: kv pad size = 2.36 MB
whisper_init_state: compute buffer (conv) = 14.17 MB
whisper_init_state: compute buffer (encode) = 65.96 MB
whisper_init_state: compute buffer (cross) = 8.50 MB
whisper_init_state: compute buffer (decode) = 96.83 ...
|
50
|
NULL
|
NULL
|
NULL
|
|
53
|
3
|
13
|
2026-05-06T17:32:25.343407+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778088745343_m1.jpg...
|
iTerm2
|
screenpipe"
|
True
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
rsync 2026-04-27/ → NAS ✓ 0m26s (242 f rsync 2026-04-27/ → NAS ✓ 0m26s (242 files, 325M)
[2026-05-06 19:41:28] Archive DB size: 9.7G
[2026-05-06 19:41:28] Total time: 19m12s
[2026-05-06 19:41:28] Sync complete for 2026-04-27
[2026-05-06 19:41:28] ========================================
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ~/.screenpipe/screenpipe_sync.sh 2026-04-28
[2026-05-06 19:44:49] ========================================
[2026-05-06 19:44:49] Screenpipe sync starting for: 2026-04-28
[2026-05-06 19:44:49] ========================================
[+00m00s] ▶ Preflight checks
Source DB: OK ( 11G)
NAS mount: OK /Volumes/screenpipe
Archive DB: exists (9.7G)
Data dir: OK (223 files, 159M)
[+00m00s] ▶ Counting source rows for 2026-04-28
frames: 4535
elements: 407532
ui_events: 8621
ocr_text: 1623
meetings: 3
[+00m02s] ▶ Initialising tables, indexes, FTS
creating tables ✓ 0m00s
creating indexes ✓ 0m00s
creating FTS tables ✓ 0m00s
[+00m02s] ▶ Syncing data for 2026-04-28
video_chunks ✓ 0m12s
frames (4535 rows) ✓ 1m30s
ocr_text (1623 rows) ✓ 0m32s
ui_events (8621 rows) ✓ 0m01s
elements (407532 rows) ✓ 1m02s
meetings (3 rows) ✓ 0m00s
[+03m19s] ▶ Updating FTS indexes
elements_fts ✓ 1m36s
frames_fts ✓ 2m28s
ui_events_fts ✓ 0m04s
[+07m27s] ▶ Verifying DB
frames: 4535 / 4535 ✓
elements: 407532 / 407532 ✓
ui_events: 8621 / 8621 ✓
ocr_text: 1623 / 1623 ✓
meetings: 3 / 3 ✓
[+08m59s] ▶ Copying data folder for 2026-04-28
rsync 2026-04-28/ → NAS ✓ 0m20s (223 files, 159M)
[2026-05-06 19:54:08] Archive DB size: 10G
[2026-05-06 19:54:08] Total time: 9m19s
[2026-05-06 19:54:08] Sync complete for 2026-04-28
[2026-05-06 19:54:08] ========================================
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ pkill -f screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ rm -rf ~/.screenpipe/
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 92 lukas staff 2944 6 May 20:22 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd .npm
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ ll
total 24
drwx------ 9 lukas staff 288 28 Apr 09:18 .
drwx------+ 92 lukas staff 2944 6 May 20:22 ..
drwx------ 5 lukas staff 160 1 Nov 2021 _cacache
drwx------@ 2 lukas staff 64 28 Apr 09:18 _locks
drwx------ 15 lukas staff 480 27 Apr 19:54 _logs
drwxr-xr-x 67 lukas staff 2144 28 Apr 09:17 _npx
-rw-r--r--@ 1 lukas staff 0 26 Apr 19:10 _update-notifier-last-checked
-rw-r--r-- 1 lukas staff 173 28 Apr 09:18 anonymous-cli-metrics.json
-rw-r--r-- 1 lukas staff 4764 31 Jan 2024 eresolve-report.txt
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ rm -rf ~/.npm/_npx
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ ll
total 52920
drwx------+ 92 lukas staff 2944 6 May 20:22 .
drwxr-xr-x 5 root admin 160 23 Aug 2024 ..
-r-------- 1 lukas staff 7 18 Nov 2021 .CFUserTextEncoding
-rw-r--r--@ 1 lukas staff 28676 27 Apr 09:11 .DS_Store
drwx------+ 10 lukas staff 320 28 Apr 17:07 .Trash
drwx------ 5 lukas staff 160 1 Nov 2021 .aws
-rw-r--r-- 1 lukas staff 341470 29 Sep 2022 .babel.json
-rw-------@ 1 lukas staff 388 25 Jul 2025 .bash_history
-rw-r--r--@ 1 lukas staff 115 18 Apr 13:19 .bashrc
drwxr-xr-x 5 lukas staff 160 11 Mar 2023 .bito
drwx------@ 6 lukas staff 192 9 Apr 19:53 .cache
drwxr-xr-x 20 lukas staff 640 27 Apr 08:58 .claude
-rw------- 1 lukas staff 28647 27 Apr 09:12 .claude.json
drwxr-xr-x@ 20 lukas staff 640 12 Mar 09:12 .codeium
drwxrwxrwx@ 3 lukas staff 96 2 Mar 2023 .composer
drwx------ 16 lukas staff 512 21 May 2025 .config
drwxr-xr-x 15 lukas staff 480 23 Dec 2024 .continue
drwx------@ 3 lukas staff 96 16 Feb 19:13 .copilot
drwxr-xr-x@ 5 lukas staff 160 9 Apr 2025 .cursor
drwxr-xr-x@ 5 lukas staff 160 17 Aug 2024 .cursor-tutor
drwxr-xr-x 3 lukas staff 96 8 Sep 2024 .daytona
drwxr-xr-x@ 4 lukas staff 128 18 Feb 10:52 .devdb
drwx------ 24 lukas staff 768 27 Apr 18:14 .docker
drwx------ 15 lukas staff 480 6 Jun 2023 .dropbox
drwxr-xr-x@ 3 lukas staff 96 20 Nov 2022 .fig.dotfiles.bak
-rw-r--r-- 1 lukas staff 138 5 Mar 2022 .gauth
-rw-r--r-- 1 lukas staff 220 25 Nov 2021 .gitconfig
-rw-r--r-- 1 lukas staff 12288 25 Nov 2021 .gitconfig.swp
drwx------ 5 lukas staff 160 18 Nov 2021 .hammerspoon
drwxr-xr-x 3 lukas staff 96 21 Mar 2025 .idlerc
-rw------- 1 lukas staff 20 28 Apr 16:51 .lesshst
drwx------ 5 lukas staff 160 23 Dec 2024 .local
-rw------- 1 lukas staff 204 16 Mar 2024 .netrc
drwx------ 3 lukas staff 96 1 Nov 2021 .node-gyp
-rw------- 1 lukas staff 4 6 Feb 2024 .node_repl_history
-rw-r--r-- 1 lukas staff 17 24 Dec 2023 .notion-enhancer
drwxr-xr-x 4 lukas staff 128 12 Jul 2024 .notion-py
drwx------ 8 lukas staff 256 6 May 20:24 .npm
-rw------- 1 lukas staff 74 20 May 2024 .npmrc
drwx------ 32 lukas staff 1024 25 Jul 2025 .nvm
drwxr-xr-x 4 lukas staff 128 5 Aug 2023 .postman
-rw-r--r--@ 1 lukas staff 77 9 Feb 2023 .profile
-rw-------@ 1 lukas staff 3153 21 Mar 2025 .python_history
drwx------ 2 lukas staff 64 15 Nov 2021 .quicktype-vscode
drwxr-xr-x@ 8 lukas staff 256 16 Feb 08:48 .redis-insight
drwxr-xr-x 4 lukas staff 128 4 Feb 09:35 .sonarlint
drwx------ 15 lukas staff 480 8 Aug 2025 .ssh
drwxr-xr-x@ 3 lukas staff 96 15 Aug 2025 .streamlit
drwx------ 6 lukas staff 192 17 Oct 2022 .swiftpm
-rw------- 1 lukas staff 12143 27 Apr 14:58 .viminfo
drwx------ 5 lukas staff 160 19 Jun 2023 .vscode
drwxr-xr-x@ 3 lukas staff 96 20 Jan 2025 .warp
UW PICO 5.09 New Buffer
[ Read 1 line ]
^G Get Help ^O WriteOut ^R Read File ^Y Prev Pg ^K Cut Text ^C Cur Pos
^X Exit ^J Justify ^W Where is ^V Next Pg ^U UnCut Text ^T To Spell
drwxr-xr-x 4 lukas staff 128 29 Apr 2023 .wdm
drwxr-xr-x@ 5 lukas staff 160 26 Jan 13:03 .windsurf
drwxr-xr-x 4 lukas staff 128 24 Mar 12:03 .yarn
-rw-r--r-- 1 lukas staff 116 30 Mar 10:12 .yarnrc
-rw-r--r-- 1 lukas staff 49518 21 Apr 09:09 .zcompdump
-rw-r--r--@ 1 lukas staff 46758 2 Nov 2025 .zcompdump.Lukas-Kovaliks-MacBook-Pro-Jiminny.23381
-rw-r--r--@ 1 lukas staff 6116 20 Apr 19:52 .zprofile
-rw-r--r-- 1 lukas staff 1468 8 Apr 2022 .zprofile-copy
-rw-r--r--@ 1 lukas staff 2900 15 Mar 2023 .zprofile.pysave
-rw------- 1 lukas staff 1731 29 Jun 2022 .zprofile.save
-rw-r--r-- 1 lukas staff 1569 8 Apr 2022 .zprofilees
-rw------- 1 lukas staff 50310 28 Apr 11:32 .zsh_history
drwx------ 9 lukas staff 288 6 May 2025 .zsh_sessions
-rw-r--r--@ 1 lukas staff 400 18 Apr 13:19 .zshrc
drwx------@ 9 lukas staff 288 20 Apr 20:55 Applications
drwxr-xr-x@ 2 lukas staff 64 22 Oct 2025 CascadeProjects
drwxr-xr-x 4 lukas staff 128 27 Oct 2025 DEV
drwx------@ 10 lukas staff 320 28 Apr 18:52 Desktop
drwx------@ 7 lukas staff 224 26 Mar 14:40 Documents
drwx------@ 44 lukas staff 1408 24 Apr 16:53 Downloads
drwxr-xr-x@ 4 lukas staff 128 17 Mar 20:27 Keychron_Screen
drwx------@ 112 lukas staff 3584 2 Dec 09:19 Library
drwx------ 7 lukas staff 224 12 Feb 2024 Movies
drwx------+ 5 lukas staff 160 25 Sep 2023 Music
drwx------+ 9 lukas staff 288 25 Sep 2023 Pictures
drwx------ 3 lukas staff 96 8 Nov 2021 Postman
drwx------+ 4 lukas staff 128 28 Oct 2021 Public
-rw-r--r--@ 1 lukas staff 3950 15 Dec 09:16 Untitled 4.spf
drwx------ 4 lukas staff 128 2 Jul 2023 Users
-rw-r--r-- 1 lukas staff 17050804 27 Apr 19:18 cleanshot-live.log
-rw-r--r-- 1 lukas staff 9363061 27 Apr 19:24 cleanshot-screenpipe.log
-rw-r--r-- 1 lukas staff 0 12 Apr 12:50 clip.mp4
-rw-r--r-- 1 lukas staff 0 12 Apr 12:51 frame.jpg
drwx------ 3 lukas staff 96 30 Sep 2022 iCloud Drive (Archive)
drwx------ 16 lukas staff 512 3 Nov 2025 jiminny
drwxr-xr-x 3 lukas staff 96 20 Mar 18:47 node_modules
drwxr-xr-x 4 lukas staff 128 21 Oct 2025 raycast
-rw-r--r-- 1 lukas staff 0 1 Mar 14:26 response.bin
-rwxr-xr-x 1 lukas staff 3824 11 Apr 15:16 screenpipe-day.sh
-rw-r--r-- 1 lukas staff 86 20 Mar 18:47 yarn.lock
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
cd: no such file or directory: /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ touch screenpipe_sync.sh
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ nano screenpipe_sync.sh
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ npx screenpipe@latest record --ignored-windows "Boosteroid" --retention-days 7
detected hardware tier: Mid
warning: parakeet is not supported on this platform, using whisper-tiny instead
2026-05-06T20:27:32.721416Z INFO screenpipe_engine::auth_key: api auth: key resolved via auto-generated
checking permissions...
screen recording: ok
microphone: ok
accessibility: ok
2026-05-06T20:27:32.831033Z INFO screenpipe_screen::monitor::macos_version: Detected macOS version: 14.6
2026-05-06T20:27:34.088403Z INFO screenpipe_engine::sleep_monitor: Starting macOS sleep/wake monitor
2026-05-06T20:27:34.089942Z INFO screenpipe_engine::sleep_monitor: Screen lock/unlock observers registered (CFNotificationCenter)
2026-05-06T20:27:34.090417Z INFO screenpipe_engine::sleep_monitor: Display reconfiguration watcher registered (CGDisplayRegisterReconfigurationCallback)
2026-05-06T20:27:34.112650Z INFO screenpipe_engine::permission_monitor: permission monitor started screen=true mic=true accessibility=true keychain=true
2026-05-06T20:27:34.112711Z INFO screenpipe: meeting detector enabled — independent of transcription mode
2026-05-06T20:27:34.619906Z INFO screenpipe: API server listening on [IP_ADDRESS]:3030 (localhost only)
2026-05-06T20:27:34.619937Z INFO screenpipe: API auth enabled — run `screenpipe auth token` to view your key
2026-05-06T20:27:34.619857Z INFO screenpipe_engine::snapshot_compaction: snapshot compaction worker started (min_age=600s, poll=300s)
2026-05-06T20:27:34.619847Z INFO screenpipe_engine::power::manager: power manager started (poll interval: 10s)
2026-05-06T20:27:34.620018Z INFO screenpipe_engine::vision_manager::manager: Starting VisionManager
2026-05-06T20:27:34.624746Z INFO screenpipe_core::pipes: installed built-in pipe: day-recap
2026-05-06T20:27:34.626304Z INFO screenpipe_core::pipes: installed built-in pipe: standup-update
2026-05-06T20:27:34.628597Z INFO screenpipe_core::pipes: installed built-in pipe: ai-habits
2026-05-06T20:27:34.629463Z INFO screenpipe_core::pipes: installed built-in pipe: time-breakdown
2026-05-06T20:27:34.630081Z INFO screenpipe_core::pipes: installed built-in pipe: video-export
2026-05-06T20:27:34.630972Z INFO screenpipe_core::pipes: installed built-in pipe: meeting-summary
2026-05-06T20:27:34.631427Z INFO screenpipe_core::pipes: loaded pipe: day-recap
2026-05-06T20:27:34.631521Z INFO screenpipe_core::pipes: loaded pipe: standup-update
2026-05-06T20:27:34.631587Z INFO screenpipe_core::pipes: loaded pipe: ai-habits
2026-05-06T20:27:34.631640Z INFO screenpipe_core::pipes: loaded pipe: time-breakdown
2026-05-06T20:27:34.631690Z INFO screenpipe_core::pipes: loaded pipe: video-export
2026-05-06T20:27:34.631738Z INFO screenpipe_core::pipes: loaded pipe: meeting-summary
2026-05-06T20:27:34.631752Z INFO screenpipe_core::pipes: loaded 6 pipes from "/Users/lukas/.screenpipe/pipes"
_
__________________ ___ ____ ____ (_____ ___
/ ___/ ___/ ___/ _ \/ _ \/ __ \ / __ \/ / __ \/ _ \
(__ / /__/ / / __/ __/ / / / / /_/ / / /_/ / __/
/____/\___/_/ \___/\___/_/ /_/ / .___/_/ .___/\___/
/_/ /_/
power AI by everything you've seen, said or heard
open source | runs locally | developer friendly
┌────────────────────────┬────────────────────────────────────┐
│ setting │ value │
├────────────────────────┼────────────────────────────────────┤
│ audio chunk duration │ 30 seconds │
│ port │ 3030 │
│ audio disabled │ false │
│ vision disabled │ false │
│ pause on DRM content │ false │
│ audio engine │ Parakeet │
│ vad engine │ Silero │
│ data directory │ /Users/lukas/.screenpipe │
│ debug mode │ false │
│ telemetry │ true │
│ use pii removal │ true │
│ use all monitors │ true │
│ ignored windows │ ["Boosteroid"] │
│ included windows │ [] │
│ cloud sync │ disabled │
│ auto-destruct pid │ 0 │
│ deepgram key │ not set │
│ api auth │ enabled │
│ encrypt secrets │ disabled │
│ retention days │ 7 │
│ retention mode │ media-only (keep transcripts) │
├────────────────────────┼────────────────────────────────────┤
│ languages │ │
│ │ all languages │
├────────────────────────┼────────────────────────────────────┤
│ monitors │ │
│ │ id: 1 │
│ │ id: 2 │
├────────────────────────┼────────────────────────────────────┤
│ audio devices │ │
│ │ MacBook Pro Microphone (input) │
│ │ System Audio (output) │
└────────────────────────┴────────────────────────────────────┘
you are using local processing. all your data stays on your computer.
warning: telemetry is enabled. only error-level data will be sent.
to disable, use the --disable-telemetry flag.
check latest changes here: [URL_WITH_CREDENTIALS] ~ $ 2026-05-06T20:31:45.865813Z INFO screenpipe_audio::device::device_manager: Stopping device: MacBook Pro Microphone (input)
2026-05-06T20:31:45.865820Z INFO screenpipe_audio::device::device_manager: Stopping device: MacBook Pro Microphone (input)
2026-05-06T20:31:45.892593Z INFO screenpipe_audio::audio_manager::manager: audio manager stopped
2026-05-06T20:31:45.892684Z INFO screenpipe: stopping UI event capture
2026-05-06T20:31:45.893002Z INFO screenpipe_engine::meeting_detector: meeting v2: shutdown received, exiting detection loop
2026-05-06T20:31:45.893977Z INFO screenpipe: received shutdown signal for VisionManager
2026-05-06T20:31:45.894556Z INFO screenpipe_engine::vision_manager::manager: Shutting down VisionManager
2026-05-06T20:31:45.894516Z INFO screenpipe_engine::snapshot_compaction: snapshot compaction worker shutting down
2026-05-06T20:31:45.894602Z INFO screenpipe_engine::vision_manager::manager: Stopping VisionManager
2026-05-06T20:31:45.895419Z INFO screenpipe_engine::vision_manager::manager: Stopping vision recording for monitor 2
2026-05-06T20:31:45.895898Z INFO screenpipe_engine::vision_manager::manager: Stopping vision recording for monitor 1
2026-05-06T20:31:45.980559Z INFO screenpipe_engine::ui_recorder: UI recording session ended: 54869993-7b4b-491f-b717-2a583517f9c5
2026-05-06T20:31:45.980777Z INFO screenpipe: shutdown complete
ggml_metal_free: deallocating
2026-05-06T20:31:46.374234Z ERROR screenpipe_engine::event_driven_capture: event capture failed (trigger=click, monitor=1): monitor capture failed: capture task panicked: task 770 was cancelled
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ ;3B
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ sp-start
detected hardware tier: Mid
warning: parakeet is not supported on this platform, using whisper-tiny instead
2026-05-06T20:32:21.850318Z INFO screenpipe_engine::auth_key: api auth: key resolved via secret store
checking permissions...
screen recording: ok
accessibility: ok
2026-05-06T20:32:21.937393Z INFO screenpipe_screen::monitor::macos_version: Detected macOS version: 14.6
2026-05-06T20:32:23.002257Z INFO screenpipe_engine::sleep_monitor: Starting macOS sleep/wake monitor
2026-05-06T20:32:23.006683Z INFO screenpipe_engine::sleep_monitor: Screen lock/unlock observers registered (CFNotificationCenter)
2026-05-06T20:32:23.008348Z INFO screenpipe_engine::sleep_monitor: Display reconfiguration watcher registered (CGDisplayRegisterReconfigurationCallback)
2026-05-06T20:32:23.030912Z INFO screenpipe_engine::permission_monitor: permission monitor started screen=true mic=true accessibility=true keychain=true
2026-05-06T20:32:23.030979Z INFO screenpipe: meeting detector enabled — independent of transcription mode
2026-05-06T20:32:23.031261Z INFO screenpipe: API server listening on [IP_ADDRESS]:3030 (localhost only)
2026-05-06T20:32:23.031328Z INFO screenpipe_engine::vision_manager::manager: Starting VisionManager
2026-05-06T20:32:23.031199Z INFO screenpipe_engine::snapshot_compaction: snapshot compaction worker started (min_age=600s, poll=300s)
2026-05-06T20:32:23.031387Z INFO screenpipe: API auth enabled — run `screenpipe auth token` to view your key
2026-05-06T20:32:23.031253Z INFO screenpipe_engine::power::manager: power manager started (poll interval: 10s)
2026-05-06T20:32:23.034682Z INFO screenpipe_core::pipes: loaded pipe: day-recap
2026-05-06T20:32:23.035042Z INFO screenpipe_core::pipes: loaded pipe: standup-update
2026-05-06T20:32:23.035480Z INFO screenpipe_core::pipes: loaded pipe: ai-habits
2026-05-06T20:32:23.035607Z INFO screenpipe_core::pipes: loaded pipe: time-breakdown
2026-05-06T20:32:23.035705Z INFO screenpipe_core::pipes: load...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"rsync 2026-04-27/ → NAS ✓ 0m26s (242 files, 325M)\n\n[2026-05-06 19:41:28] Archive DB size: 9.7G\n[2026-05-06 19:41:28] Total time: 19m12s\n[2026-05-06 19:41:28] Sync complete for 2026-04-27\n[2026-05-06 19:41:28] ========================================\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ~/.screenpipe/screenpipe_sync.sh 2026-04-28\n[2026-05-06 19:44:49] ========================================\n[2026-05-06 19:44:49] Screenpipe sync starting for: 2026-04-28\n[2026-05-06 19:44:49] ========================================\n\n[+00m00s] ▶ Preflight checks\n Source DB: OK ( 11G)\n NAS mount: OK /Volumes/screenpipe\n Archive DB: exists (9.7G)\n Data dir: OK (223 files, 159M)\n\n[+00m00s] ▶ Counting source rows for 2026-04-28\n frames: 4535\n elements: 407532\n ui_events: 8621\n ocr_text: 1623\n meetings: 3\n\n[+00m02s] ▶ Initialising tables, indexes, FTS\n creating tables ✓ 0m00s\n creating indexes ✓ 0m00s\n creating FTS tables ✓ 0m00s\n\n[+00m02s] ▶ Syncing data for 2026-04-28\n video_chunks ✓ 0m12s\n frames (4535 rows) ✓ 1m30s\n ocr_text (1623 rows) ✓ 0m32s\n ui_events (8621 rows) ✓ 0m01s\n elements (407532 rows) ✓ 1m02s\n meetings (3 rows) ✓ 0m00s\n\n[+03m19s] ▶ Updating FTS indexes\n elements_fts ✓ 1m36s\n frames_fts ✓ 2m28s\n ui_events_fts ✓ 0m04s\n\n[+07m27s] ▶ Verifying DB\n frames: 4535 / 4535 ✓\n elements: 407532 / 407532 ✓\n ui_events: 8621 / 8621 ✓\n ocr_text: 1623 / 1623 ✓\n meetings: 3 / 3 ✓\n\n[+08m59s] ▶ Copying data folder for 2026-04-28\n rsync 2026-04-28/ → NAS ✓ 0m20s (223 files, 159M)\n\n[2026-05-06 19:54:08] Archive DB size: 10G\n[2026-05-06 19:54:08] Total time: 9m19s\n[2026-05-06 19:54:08] Sync complete for 2026-04-28\n[2026-05-06 19:54:08] ========================================\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ pkill -f screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ rm -rf ~/.screenpipe/\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 92 lukas staff 2944 6 May 20:22 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd .npm \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ ll\ntotal 24\ndrwx------ 9 lukas staff 288 28 Apr 09:18 .\ndrwx------+ 92 lukas staff 2944 6 May 20:22 ..\ndrwx------ 5 lukas staff 160 1 Nov 2021 _cacache\ndrwx------@ 2 lukas staff 64 28 Apr 09:18 _locks\ndrwx------ 15 lukas staff 480 27 Apr 19:54 _logs\ndrwxr-xr-x 67 lukas staff 2144 28 Apr 09:17 _npx\n-rw-r--r--@ 1 lukas staff 0 26 Apr 19:10 _update-notifier-last-checked\n-rw-r--r-- 1 lukas staff 173 28 Apr 09:18 anonymous-cli-metrics.json\n-rw-r--r-- 1 lukas staff 4764 31 Jan 2024 eresolve-report.txt\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ rm -rf ~/.npm/_npx\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ ll \ntotal 52920\ndrwx------+ 92 lukas staff 2944 6 May 20:22 .\ndrwxr-xr-x 5 root admin 160 23 Aug 2024 ..\n-r-------- 1 lukas staff 7 18 Nov 2021 .CFUserTextEncoding\n-rw-r--r--@ 1 lukas staff 28676 27 Apr 09:11 .DS_Store\ndrwx------+ 10 lukas staff 320 28 Apr 17:07 .Trash\ndrwx------ 5 lukas staff 160 1 Nov 2021 .aws\n-rw-r--r-- 1 lukas staff 341470 29 Sep 2022 .babel.json\n-rw-------@ 1 lukas staff 388 25 Jul 2025 .bash_history\n-rw-r--r--@ 1 lukas staff 115 18 Apr 13:19 .bashrc\ndrwxr-xr-x 5 lukas staff 160 11 Mar 2023 .bito\ndrwx------@ 6 lukas staff 192 9 Apr 19:53 .cache\ndrwxr-xr-x 20 lukas staff 640 27 Apr 08:58 .claude\n-rw------- 1 lukas staff 28647 27 Apr 09:12 .claude.json\ndrwxr-xr-x@ 20 lukas staff 640 12 Mar 09:12 .codeium\ndrwxrwxrwx@ 3 lukas staff 96 2 Mar 2023 .composer\ndrwx------ 16 lukas staff 512 21 May 2025 .config\ndrwxr-xr-x 15 lukas staff 480 23 Dec 2024 .continue\ndrwx------@ 3 lukas staff 96 16 Feb 19:13 .copilot\ndrwxr-xr-x@ 5 lukas staff 160 9 Apr 2025 .cursor\ndrwxr-xr-x@ 5 lukas staff 160 17 Aug 2024 .cursor-tutor\ndrwxr-xr-x 3 lukas staff 96 8 Sep 2024 .daytona\ndrwxr-xr-x@ 4 lukas staff 128 18 Feb 10:52 .devdb\ndrwx------ 24 lukas staff 768 27 Apr 18:14 .docker\ndrwx------ 15 lukas staff 480 6 Jun 2023 .dropbox\ndrwxr-xr-x@ 3 lukas staff 96 20 Nov 2022 .fig.dotfiles.bak\n-rw-r--r-- 1 lukas staff 138 5 Mar 2022 .gauth\n-rw-r--r-- 1 lukas staff 220 25 Nov 2021 .gitconfig\n-rw-r--r-- 1 lukas staff 12288 25 Nov 2021 .gitconfig.swp\ndrwx------ 5 lukas staff 160 18 Nov 2021 .hammerspoon\ndrwxr-xr-x 3 lukas staff 96 21 Mar 2025 .idlerc\n-rw------- 1 lukas staff 20 28 Apr 16:51 .lesshst\ndrwx------ 5 lukas staff 160 23 Dec 2024 .local\n-rw------- 1 lukas staff 204 16 Mar 2024 .netrc\ndrwx------ 3 lukas staff 96 1 Nov 2021 .node-gyp\n-rw------- 1 lukas staff 4 6 Feb 2024 .node_repl_history\n-rw-r--r-- 1 lukas staff 17 24 Dec 2023 .notion-enhancer\ndrwxr-xr-x 4 lukas staff 128 12 Jul 2024 .notion-py\ndrwx------ 8 lukas staff 256 6 May 20:24 .npm\n-rw------- 1 lukas staff 74 20 May 2024 .npmrc\ndrwx------ 32 lukas staff 1024 25 Jul 2025 .nvm\ndrwxr-xr-x 4 lukas staff 128 5 Aug 2023 .postman\n-rw-r--r--@ 1 lukas staff 77 9 Feb 2023 .profile\n-rw-------@ 1 lukas staff 3153 21 Mar 2025 .python_history\ndrwx------ 2 lukas staff 64 15 Nov 2021 .quicktype-vscode\ndrwxr-xr-x@ 8 lukas staff 256 16 Feb 08:48 .redis-insight\ndrwxr-xr-x 4 lukas staff 128 4 Feb 09:35 .sonarlint\ndrwx------ 15 lukas staff 480 8 Aug 2025 .ssh\ndrwxr-xr-x@ 3 lukas staff 96 15 Aug 2025 .streamlit\ndrwx------ 6 lukas staff 192 17 Oct 2022 .swiftpm\n-rw------- 1 lukas staff 12143 27 Apr 14:58 .viminfo\ndrwx------ 5 lukas staff 160 19 Jun 2023 .vscode\ndrwxr-xr-x@ 3 lukas staff 96 20 Jan 2025 .warp\n UW PICO 5.09 New Buffer \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n [ Read 1 line ] \n^G Get Help ^O WriteOut ^R Read File ^Y Prev Pg ^K Cut Text ^C Cur Pos \n^X Exit ^J Justify ^W Where is ^V Next Pg ^U UnCut Text ^T To Spell \ndrwxr-xr-x 4 lukas staff 128 29 Apr 2023 .wdm\ndrwxr-xr-x@ 5 lukas staff 160 26 Jan 13:03 .windsurf\ndrwxr-xr-x 4 lukas staff 128 24 Mar 12:03 .yarn\n-rw-r--r-- 1 lukas staff 116 30 Mar 10:12 .yarnrc\n-rw-r--r-- 1 lukas staff 49518 21 Apr 09:09 .zcompdump\n-rw-r--r--@ 1 lukas staff 46758 2 Nov 2025 .zcompdump.Lukas-Kovaliks-MacBook-Pro-Jiminny.23381\n-rw-r--r--@ 1 lukas staff 6116 20 Apr 19:52 .zprofile\n-rw-r--r-- 1 lukas staff 1468 8 Apr 2022 .zprofile-copy\n-rw-r--r--@ 1 lukas staff 2900 15 Mar 2023 .zprofile.pysave\n-rw------- 1 lukas staff 1731 29 Jun 2022 .zprofile.save\n-rw-r--r-- 1 lukas staff 1569 8 Apr 2022 .zprofilees\n-rw------- 1 lukas staff 50310 28 Apr 11:32 .zsh_history\ndrwx------ 9 lukas staff 288 6 May 2025 .zsh_sessions\n-rw-r--r--@ 1 lukas staff 400 18 Apr 13:19 .zshrc\ndrwx------@ 9 lukas staff 288 20 Apr 20:55 Applications\ndrwxr-xr-x@ 2 lukas staff 64 22 Oct 2025 CascadeProjects\ndrwxr-xr-x 4 lukas staff 128 27 Oct 2025 DEV\ndrwx------@ 10 lukas staff 320 28 Apr 18:52 Desktop\ndrwx------@ 7 lukas staff 224 26 Mar 14:40 Documents\ndrwx------@ 44 lukas staff 1408 24 Apr 16:53 Downloads\ndrwxr-xr-x@ 4 lukas staff 128 17 Mar 20:27 Keychron_Screen\ndrwx------@ 112 lukas staff 3584 2 Dec 09:19 Library\ndrwx------ 7 lukas staff 224 12 Feb 2024 Movies\ndrwx------+ 5 lukas staff 160 25 Sep 2023 Music\ndrwx------+ 9 lukas staff 288 25 Sep 2023 Pictures\ndrwx------ 3 lukas staff 96 8 Nov 2021 Postman\ndrwx------+ 4 lukas staff 128 28 Oct 2021 Public\n-rw-r--r--@ 1 lukas staff 3950 15 Dec 09:16 Untitled 4.spf\ndrwx------ 4 lukas staff 128 2 Jul 2023 Users\n-rw-r--r-- 1 lukas staff 17050804 27 Apr 19:18 cleanshot-live.log\n-rw-r--r-- 1 lukas staff 9363061 27 Apr 19:24 cleanshot-screenpipe.log\n-rw-r--r-- 1 lukas staff 0 12 Apr 12:50 clip.mp4\n-rw-r--r-- 1 lukas staff 0 12 Apr 12:51 frame.jpg\ndrwx------ 3 lukas staff 96 30 Sep 2022 iCloud Drive (Archive)\ndrwx------ 16 lukas staff 512 3 Nov 2025 jiminny\ndrwxr-xr-x 3 lukas staff 96 20 Mar 18:47 node_modules\ndrwxr-xr-x 4 lukas staff 128 21 Oct 2025 raycast\n-rw-r--r-- 1 lukas staff 0 1 Mar 14:26 response.bin\n-rwxr-xr-x 1 lukas staff 3824 11 Apr 15:16 screenpipe-day.sh\n-rw-r--r-- 1 lukas staff 86 20 Mar 18:47 yarn.lock\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe\ncd: no such file or directory: /Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ touch screenpipe_sync.sh\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ nano screenpipe_sync.sh\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ npx screenpipe@latest record --ignored-windows \"Boosteroid\" --retention-days 7\ndetected hardware tier: Mid\nwarning: parakeet is not supported on this platform, using whisper-tiny instead\n2026-05-06T20:27:32.721416Z INFO screenpipe_engine::auth_key: api auth: key resolved via auto-generated\nchecking permissions...\n screen recording: ok\n microphone: ok\n accessibility: ok\n2026-05-06T20:27:32.831033Z INFO screenpipe_screen::monitor::macos_version: Detected macOS version: 14.6\n2026-05-06T20:27:34.088403Z INFO screenpipe_engine::sleep_monitor: Starting macOS sleep/wake monitor\n2026-05-06T20:27:34.089942Z INFO screenpipe_engine::sleep_monitor: Screen lock/unlock observers registered (CFNotificationCenter)\n2026-05-06T20:27:34.090417Z INFO screenpipe_engine::sleep_monitor: Display reconfiguration watcher registered (CGDisplayRegisterReconfigurationCallback)\n2026-05-06T20:27:34.112650Z INFO screenpipe_engine::permission_monitor: permission monitor started screen=true mic=true accessibility=true keychain=true\n2026-05-06T20:27:34.112711Z INFO screenpipe: meeting detector enabled — independent of transcription mode\n2026-05-06T20:27:34.619906Z INFO screenpipe: API server listening on 127.0.0.1:3030 (localhost only)\n2026-05-06T20:27:34.619937Z INFO screenpipe: API auth enabled — run `screenpipe auth token` to view your key\n2026-05-06T20:27:34.619857Z INFO screenpipe_engine::snapshot_compaction: snapshot compaction worker started (min_age=600s, poll=300s)\n2026-05-06T20:27:34.619847Z INFO screenpipe_engine::power::manager: power manager started (poll interval: 10s)\n2026-05-06T20:27:34.620018Z INFO screenpipe_engine::vision_manager::manager: Starting VisionManager\n2026-05-06T20:27:34.624746Z INFO screenpipe_core::pipes: installed built-in pipe: day-recap\n2026-05-06T20:27:34.626304Z INFO screenpipe_core::pipes: installed built-in pipe: standup-update\n2026-05-06T20:27:34.628597Z INFO screenpipe_core::pipes: installed built-in pipe: ai-habits\n2026-05-06T20:27:34.629463Z INFO screenpipe_core::pipes: installed built-in pipe: time-breakdown\n2026-05-06T20:27:34.630081Z INFO screenpipe_core::pipes: installed built-in pipe: video-export\n2026-05-06T20:27:34.630972Z INFO screenpipe_core::pipes: installed built-in pipe: meeting-summary\n2026-05-06T20:27:34.631427Z INFO screenpipe_core::pipes: loaded pipe: day-recap\n2026-05-06T20:27:34.631521Z INFO screenpipe_core::pipes: loaded pipe: standup-update\n2026-05-06T20:27:34.631587Z INFO screenpipe_core::pipes: loaded pipe: ai-habits\n2026-05-06T20:27:34.631640Z INFO screenpipe_core::pipes: loaded pipe: time-breakdown\n2026-05-06T20:27:34.631690Z INFO screenpipe_core::pipes: loaded pipe: video-export\n2026-05-06T20:27:34.631738Z INFO screenpipe_core::pipes: loaded pipe: meeting-summary\n2026-05-06T20:27:34.631752Z INFO screenpipe_core::pipes: loaded 6 pipes from \"/Users/lukas/.screenpipe/pipes\"\n\n\n\n _ \n __________________ ___ ____ ____ (_____ ___ \n / ___/ ___/ ___/ _ \\/ _ \\/ __ \\ / __ \\/ / __ \\/ _ \\\n (__ / /__/ / / __/ __/ / / / / /_/ / / /_/ / __/\n/____/\\___/_/ \\___/\\___/_/ /_/ / .___/_/ .___/\\___/ \n /_/ /_/ \n\n\n\npower AI by everything you've seen, said or heard\nopen source | runs locally | developer friendly\n\n\n┌────────────────────────┬────────────────────────────────────┐\n│ setting │ value │\n├────────────────────────┼────────────────────────────────────┤\n│ audio chunk duration │ 30 seconds │\n│ port │ 3030 │\n│ audio disabled │ false │\n│ vision disabled │ false │\n│ pause on DRM content │ false │\n│ audio engine │ Parakeet │\n│ vad engine │ Silero │\n│ data directory │ /Users/lukas/.screenpipe │\n│ debug mode │ false │\n│ telemetry │ true │\n│ use pii removal │ true │\n│ use all monitors │ true │\n│ ignored windows │ [\"Boosteroid\"] │\n│ included windows │ [] │\n│ cloud sync │ disabled │\n│ auto-destruct pid │ 0 │\n│ deepgram key │ not set │\n│ api auth │ enabled │\n│ encrypt secrets │ disabled │\n│ retention days │ 7 │\n│ retention mode │ media-only (keep transcripts) │\n├────────────────────────┼────────────────────────────────────┤\n│ languages │ │\n│ │ all languages │\n├────────────────────────┼────────────────────────────────────┤\n│ monitors │ │\n│ │ id: 1 │\n│ │ id: 2 │\n├────────────────────────┼────────────────────────────────────┤\n│ audio devices │ │\n│ │ MacBook Pro Microphone (input) │\n│ │ System Audio (output) │\n└────────────────────────┴────────────────────────────────────┘\nyou are using local processing. all your data stays on your computer.\n\nwarning: telemetry is enabled. only error-level data will be sent.\nto disable, use the --disable-telemetry flag.\n\ncheck latest changes here: https://github.com/screenpipe/screenpipe/releases\n2026-05-06T20:27:34.638384Z INFO screenpipe: starting UI event capture\n2026-05-06T20:27:34.637679Z INFO screenpipe_core::pipes: pipe scheduler started (generation 2)\n2026-05-06T20:27:34.649154Z INFO screenpipe_engine::power::manager: initial power profile: Performance (on_ac=true, battery=Some(94))\n2026-05-06T20:27:34.652794Z WARN screenpipe: pi agent install failed: bun not found — install from https://bun.sh\n2026-05-06T20:27:34.655839Z INFO screenpipe_engine::ui_recorder: Starting UI event capture\n2026-05-06T20:27:34.673877Z INFO screenpipe_engine::ui_recorder: UI recording session started: 54869993-7b4b-491f-b717-2a583517f9c5\n2026-05-06T20:27:34.673910Z INFO screenpipe_engine::calendar_speaker_id: speaker identification: started (user_name=<not set>)\n2026-05-06T20:27:34.674057Z INFO screenpipe_engine::hot_frame_cache: hot_frame_cache: warming from DB (2026-05-05 17:27:34.674056 UTC to 2026-05-06 17:27:34.674056 UTC)\n2026-05-06T20:27:34.674892Z INFO screenpipe_engine::meeting_detector: meeting v2: detection loop started (base_interval=5s, profiles=12)\n2026-05-06T20:27:34.675788Z INFO screenpipe_engine::hot_frame_cache: hot_frame_cache: warmed with 0 frame entries, coverage from 2026-05-05 17:27:34.674056 UTC\n2026-05-06T20:27:34.686546Z INFO screenpipe_engine::server: Server listening on 127.0.0.1:3030\n2026-05-06T20:27:34.691371Z INFO screenpipe_connect::mdns: mdns: advertising screenpipe on port 3030\n2026-05-06T20:27:36.270608Z INFO screenpipe_engine::vision_manager::manager: Starting vision recording for monitor 1 (1440x900)\n2026-05-06T20:27:36.270669Z INFO screenpipe_engine::vision_manager::manager: Starting event-driven capture for monitor 1 (device: monitor_1)\n2026-05-06T20:27:36.270714Z INFO screenpipe_engine::event_driven_capture: event-driven capture started for monitor 1 (device: monitor_1)\n2026-05-06T20:27:36.932583Z INFO screenpipe_engine::vision_manager::manager: Starting vision recording for monitor 2 (3008x1253)\n2026-05-06T20:27:36.932852Z INFO screenpipe_engine::vision_manager::manager: Starting event-driven capture for monitor 2 (device: monitor_2)\n2026-05-06T20:27:36.932882Z INFO screenpipe_engine::vision_manager::manager: VisionManager started with 2/2 monitor(s)\n2026-05-06T20:27:36.932899Z INFO screenpipe_engine::vision_manager::monitor_watcher: Starting monitor watcher (event-driven via CGDisplayRegisterReconfigurationCallback, 60s backstop poll)\n2026-05-06T20:27:36.932901Z INFO screenpipe_engine::event_driven_capture: event-driven capture started for monitor 2 (device: monitor_2)\n2026-05-06T20:27:39.158281Z INFO sck_rs::stream_manager: persistent SCK stream started for display 1 (1440x900, 2fps, 3 excluded)\n2026-05-06T20:27:39.593177Z INFO screenpipe_engine::event_driven_capture: startup capture for monitor 1: frame_id=1, dur=101ms\n2026-05-06T20:27:40.672366Z INFO sck_rs::stream_manager: persistent SCK stream started for display 2 (3008x1253, 2fps, 3 excluded)\n2026-05-06T20:27:41.257664Z INFO screenpipe_engine::event_driven_capture: startup capture for monitor 2: frame_id=2, dur=140ms\n2026-05-06T20:27:44.641022Z INFO screenpipe_audio::transcription::engine: whisper model available: \"/Users/lukas/.cache/huggingface/hub/models--ggerganov--whisper.cpp/snapshots/5359861c739e955e79d9a303bcbc70fb988958b1/ggml-tiny.bin\"\n2026-05-06T20:27:44.641079Z INFO screenpipe_audio::transcription::whisper::model: whisper context: gpu acceleration enabled (Metal on macOS, Vulkan on Windows)\n2026-05-06T20:27:44.641086Z INFO screenpipe_audio::transcription::engine: loading whisper model with GPU acceleration...\nwhisper_init_from_file_with_params_no_state: loading model from '/Users/lukas/.cache/huggingface/hub/models--ggerganov--whisper.cpp/snapshots/5359861c739e955e79d9a303bcbc70fb988958b1/ggml-tiny.bin'\nwhisper_init_with_params_no_state: use gpu = 1\nwhisper_init_with_params_no_state: flash attn = 0\nwhisper_init_with_params_no_state: gpu_device = 0\nwhisper_init_with_params_no_state: dtw = 0\nggml_metal_device_init: tensor API disabled for pre-M5 and pre-A19 devices\nggml_metal_library_init: using embedded metal library\nggml_metal_library_init: loaded in 0.041 sec\nggml_metal_rsets_init: creating a residency set collection (keep_alive = 180 s)\nggml_metal_device_init: GPU name: Apple M1\nggml_metal_device_init: GPU family: MTLGPUFamilyApple7 (1007)\nggml_metal_device_init: GPU family: MTLGPUFamilyCommon3 (3003)\nggml_metal_device_init: GPU family: MTLGPUFamilyMetal3 (5001)\nggml_metal_device_init: simdgroup reduction = true\nggml_metal_device_init: simdgroup matrix mul. = true\nggml_metal_device_init: has unified memory = true\nggml_metal_device_init: has bfloat = true\nggml_metal_device_init: has tensor = false\nggml_metal_device_init: use residency sets = true\nggml_metal_device_init: use shared buffers = true\nggml_metal_device_init: recommendedMaxWorkingSetSize = 11453.25 MB\nwhisper_init_with_params_no_state: devices = 3\nwhisper_init_with_params_no_state: backends = 3\nwhisper_model_load: loading model\nwhisper_model_load: n_vocab = 51865\nwhisper_model_load: n_audio_ctx = 1500\nwhisper_model_load: n_audio_state = 384\nwhisper_model_load: n_audio_head = 6\nwhisper_model_load: n_audio_layer = 4\nwhisper_model_load: n_text_ctx = 448\nwhisper_model_load: n_text_state = 384\nwhisper_model_load: n_text_head = 6\nwhisper_model_load: n_text_layer = 4\nwhisper_model_load: n_mels = 80\nwhisper_model_load: ftype = 1\nwhisper_model_load: qntvr = 0\nwhisper_model_load: type = 1 (tiny)\nwhisper_model_load: adding 1608 extra tokens\nwhisper_model_load: n_langs = 99\nwhisper_model_load: Metal total size = 77.11 MB\nwhisper_model_load: model size = 77.11 MB\n2026-05-06T20:27:44.857210Z INFO screenpipe_audio::transcription::engine: whisper model loaded successfully\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\n2026-05-06T20:27:44.861912Z INFO screenpipe_audio::audio_manager::manager: transcription session created (will be reused across segments)\n2026-05-06T20:27:44.862480Z INFO screenpipe_audio::audio_manager::manager: audio manager started\n2026-05-06T20:27:44.862525Z INFO screenpipe_audio::audio_manager::manager: calendar-assisted speaker diarization: listening for meeting events\n2026-05-06T20:27:47.831980Z INFO screenpipe_audio::device::device_manager: starting recording for device: System Audio (output)\n2026-05-06T20:27:47.832191Z INFO screenpipe_audio::core::run_record_and_transcribe: starting continuous recording for System Audio (output) (unknown / 30s segments)\n2026-05-06T20:27:47.906029Z INFO screenpipe_audio::device::device_manager: starting recording for device: MacBook Pro Microphone (input)\n2026-05-06T20:27:47.906090Z INFO screenpipe_audio::core::run_record_and_transcribe: starting continuous recording for MacBook Pro Microphone (input) (wired / 30s segments)\n2026-05-06T20:28:15.251258Z INFO screenpipe_engine::event_driven_capture: content dedup: skipping capture for monitor 1 (hash=-8608554010568040663, trigger=visual_change)\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\n2026-05-06T20:29:45.187551Z INFO screenpipe_audio::audio_manager::manager: reconciliation: transcribed 6 orphaned chunks\n2026-05-06T20:30:06.916244Z WARN screenpipe_audio::core::source_buffer: [MacBook Pro Microphone (input)] large gap on wired device: 81.4ms elapsed (expected 5.3ms) → inserting 76.0ms silence (7299 samples)\n2026-05-06T20:30:29.881247Z WARN screenpipe_audio::core::source_buffer: [MacBook Pro Microphone (input)] large gap on wired device: 96.0ms elapsed (expected 5.3ms) → inserting 90.7ms silence (8704 samples)\n^C2026-05-06T20:31:44.992913Z INFO screenpipe: received ctrl+c, initiating shutdown\n2026-05-06T20:31:44.993815Z INFO screenpipe_audio::device::device_manager: Stopping device: System Audio (output)\n2026-05-06T20:31:44.993845Z INFO screenpipe_audio::device::device_manager: Stopping device: System Audio (output)\n\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ 2026-05-06T20:31:45.865813Z INFO screenpipe_audio::device::device_manager: Stopping device: MacBook Pro Microphone (input)\n2026-05-06T20:31:45.865820Z INFO screenpipe_audio::device::device_manager: Stopping device: MacBook Pro Microphone (input)\n2026-05-06T20:31:45.892593Z INFO screenpipe_audio::audio_manager::manager: audio manager stopped\n2026-05-06T20:31:45.892684Z INFO screenpipe: stopping UI event capture\n2026-05-06T20:31:45.893002Z INFO screenpipe_engine::meeting_detector: meeting v2: shutdown received, exiting detection loop\n2026-05-06T20:31:45.893977Z INFO screenpipe: received shutdown signal for VisionManager\n2026-05-06T20:31:45.894556Z INFO screenpipe_engine::vision_manager::manager: Shutting down VisionManager\n2026-05-06T20:31:45.894516Z INFO screenpipe_engine::snapshot_compaction: snapshot compaction worker shutting down\n2026-05-06T20:31:45.894602Z INFO screenpipe_engine::vision_manager::manager: Stopping VisionManager\n2026-05-06T20:31:45.895419Z INFO screenpipe_engine::vision_manager::manager: Stopping vision recording for monitor 2\n2026-05-06T20:31:45.895898Z INFO screenpipe_engine::vision_manager::manager: Stopping vision recording for monitor 1\n2026-05-06T20:31:45.980559Z INFO screenpipe_engine::ui_recorder: UI recording session ended: 54869993-7b4b-491f-b717-2a583517f9c5\n2026-05-06T20:31:45.980777Z INFO screenpipe: shutdown complete\nggml_metal_free: deallocating\n2026-05-06T20:31:46.374234Z ERROR screenpipe_engine::event_driven_capture: event capture failed (trigger=click, monitor=1): monitor capture failed: capture task panicked: task 770 was cancelled\n\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ ;3B\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ sp-start\ndetected hardware tier: Mid\nwarning: parakeet is not supported on this platform, using whisper-tiny instead\n2026-05-06T20:32:21.850318Z INFO screenpipe_engine::auth_key: api auth: key resolved via secret store\nchecking permissions...\n screen recording: ok\n accessibility: ok\n2026-05-06T20:32:21.937393Z INFO screenpipe_screen::monitor::macos_version: Detected macOS version: 14.6\n2026-05-06T20:32:23.002257Z INFO screenpipe_engine::sleep_monitor: Starting macOS sleep/wake monitor\n2026-05-06T20:32:23.006683Z INFO screenpipe_engine::sleep_monitor: Screen lock/unlock observers registered (CFNotificationCenter)\n2026-05-06T20:32:23.008348Z INFO screenpipe_engine::sleep_monitor: Display reconfiguration watcher registered (CGDisplayRegisterReconfigurationCallback)\n2026-05-06T20:32:23.030912Z INFO screenpipe_engine::permission_monitor: permission monitor started screen=true mic=true accessibility=true keychain=true\n2026-05-06T20:32:23.030979Z INFO screenpipe: meeting detector enabled — independent of transcription mode\n2026-05-06T20:32:23.031261Z INFO screenpipe: API server listening on 127.0.0.1:3030 (localhost only)\n2026-05-06T20:32:23.031328Z INFO screenpipe_engine::vision_manager::manager: Starting VisionManager\n2026-05-06T20:32:23.031199Z INFO screenpipe_engine::snapshot_compaction: snapshot compaction worker started (min_age=600s, poll=300s)\n2026-05-06T20:32:23.031387Z INFO screenpipe: API auth enabled — run `screenpipe auth token` to view your key\n2026-05-06T20:32:23.031253Z INFO screenpipe_engine::power::manager: power manager started (poll interval: 10s)\n2026-05-06T20:32:23.034682Z INFO screenpipe_core::pipes: loaded pipe: day-recap\n2026-05-06T20:32:23.035042Z INFO screenpipe_core::pipes: loaded pipe: standup-update\n2026-05-06T20:32:23.035480Z INFO screenpipe_core::pipes: loaded pipe: ai-habits\n2026-05-06T20:32:23.035607Z INFO screenpipe_core::pipes: loaded pipe: time-breakdown\n2026-05-06T20:32:23.035705Z INFO screenpipe_core::pipes: loaded pipe: video-export\n2026-05-06T20:32:23.035815Z INFO screenpipe_core::pipes: loaded pipe: meeting-summary\n2026-05-06T20:32:23.035838Z INFO screenpipe_core::pipes: loaded 6 pipes from \"/Users/lukas/.screenpipe/pipes\"\n\n\n\n _ \n __________________ ___ ____ ____ (_____ ___ \n / ___/ ___/ ___/ _ \\/ _ \\/ __ \\ / __ \\/ / __ \\/ _ \\\n (__ / /__/ / / __/ __/ / / / / /_/ / / /_/ / __/\n/____/\\___/_/ \\___/\\___/_/ /_/ / .___/_/ .___/\\___/ \n /_/ /_/ \n\n\n\npower AI by everything you've seen, said or heard\nopen source | runs locally | developer friendly\n\n\n┌────────────────────────┬────────────────────────────────────┐\n│ setting │ value │\n├────────────────────────┼────────────────────────────────────┤\n│ audio chunk duration │ 30 seconds │\n│ port │ 3030 │\n│ audio disabled │ true │\n│ vision disabled │ false │\n│ pause on DRM content │ false │\n│ audio engine │ Parakeet │\n│ vad engine │ Silero │\n│ data directory │ /Users/lukas/.screenpipe │\n│ debug mode │ false │\n│ telemetry │ true │\n│ use pii removal │ true │\n│ use all monitors │ true │\n2026-05-06T20:32:23.037534Z INFO screenpipe_core::pipes: pipe scheduler started (generation 2)\n│ ignored windows │ [\"Boosteroid\"] │\n│ included windows │ [] │\n│ cloud sync │ disabled │\n│ auto-destruct pid │ 0 │\n│ deepgram key │ not set │\n│ api auth │ enabled │\n│ encrypt secrets │ disabled │\n│ retention days │ 14 │\n│ retention mode │ media-only (keep transcripts) │\n├────────────────────────┼────────────────────────────────────┤\n│ languages │ │\n│ │ all languages │\n├────────────────────────┼────────────────────────────────────┤\n│ monitors │ │\n│ │ id: 1 │\n│ │ id: 2 │\n├────────────────────────┼────────────────────────────────────┤\n│ audio devices │ │\n│ │ disabled │\n└────────────────────────┴────────────────────────────────────┘\nyou are using local processing. all your data stays on your computer.\n\nwarning: telemetry is enabled. only error-level data will be sent.\nto disable, use the --disable-telemetry flag.\n\ncheck latest changes here: https://github.com/screenpipe/screenpipe/releases\n2026-05-06T20:32:23.038046Z INFO screenpipe: starting UI event capture\n2026-05-06T20:32:23.058967Z WARN screenpipe: pi agent install failed: bun not found — install from https://bun.sh\n2026-05-06T20:32:23.060289Z INFO screenpipe_engine::power::manager: initial power profile: Performance (on_ac=true, battery=Some(95))\n2026-05-06T20:32:23.082491Z INFO screenpipe_engine::ui_recorder: Starting UI event capture\n2026-05-06T20:32:23.103681Z INFO screenpipe_engine::ui_recorder: UI recording session started: 83716bbd-ad71-45f9-9fba-e5b2bd8a5a97\n2026-05-06T20:32:23.103826Z INFO screenpipe_engine::calendar_speaker_id: speaker identification: started (user_name=<not set>)\n2026-05-06T20:32:23.103903Z INFO screenpipe_engine::hot_frame_cache: hot_frame_cache: warming from DB (2026-05-05 17:32:23.103901 UTC to 2026-05-06 17:32:23.103901 UTC)\n2026-05-06T20:32:23.107276Z INFO screenpipe_engine::meeting_detector: meeting v2: detection loop started (base_interval=5s, profiles=12)\n2026-05-06T20:32:23.116788Z INFO screenpipe_engine::server: Server listening on 127.0.0.1:3030\n2026-05-06T20:32:23.126899Z INFO screenpipe_connect::mdns: mdns: advertising screenpipe on port 3030\n2026-05-06T20:32:23.132524Z INFO screenpipe_engine::hot_frame_cache: hot_frame_cache: warmed with 52 frame entries, coverage from 2026-05-05 17:32:23.103901 UTC\n2026-05-06T20:32:24.842085Z INFO screenpipe_engine::vision_manager::manager: Starting vision recording for monitor 1 (1440x900)\n2026-05-06T20:32:24.842155Z INFO screenpipe_engine::vision_manager::manager: Starting event-driven capture for monitor 1 (device: monitor_1)\n2026-05-06T20:32:24.842202Z INFO screenpipe_engine::event_driven_capture: event-driven capture started for monitor 1 (device: monitor_1)\n2026-05-06T20:32:25.405285Z INFO screenpipe_engine::vision_manager::manager: Starting vision recording for monitor 2 (3008x1253)\n2026-05-06T20:32:25.405525Z INFO screenpipe_engine::vision_manager::manager: Starting event-driven capture for monitor 2 (device: monitor_2)\n2026-05-06T20:32:25.405604Z INFO screenpipe_engine::vision_manager::manager: VisionManager started with 2/2 monitor(s)\n2026-05-06T20:32:25.405641Z INFO screenpipe_engine::vision_manager::monitor_watcher: Starting monitor watcher (event-driven via CGDisplayRegisterReconfigurationCallback, 60s backstop poll)\n2026-05-06T20:32:25.405632Z INFO screenpipe_engine::event_driven_capture: event-driven capture started for monitor 2 (device: monitor_2)\n2026-05-06T20:32:27.627877Z INFO sck_rs::stream_manager: persistent SCK stream started for display 1 (1440x900, 2fps, 3 excluded)","depth":4,"on_screen":true,"value":"rsync 2026-04-27/ → NAS ✓ 0m26s (242 files, 325M)\n\n[2026-05-06 19:41:28] Archive DB size: 9.7G\n[2026-05-06 19:41:28] Total time: 19m12s\n[2026-05-06 19:41:28] Sync complete for 2026-04-27\n[2026-05-06 19:41:28] ========================================\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ~/.screenpipe/screenpipe_sync.sh 2026-04-28\n[2026-05-06 19:44:49] ========================================\n[2026-05-06 19:44:49] Screenpipe sync starting for: 2026-04-28\n[2026-05-06 19:44:49] ========================================\n\n[+00m00s] ▶ Preflight checks\n Source DB: OK ( 11G)\n NAS mount: OK /Volumes/screenpipe\n Archive DB: exists (9.7G)\n Data dir: OK (223 files, 159M)\n\n[+00m00s] ▶ Counting source rows for 2026-04-28\n frames: 4535\n elements: 407532\n ui_events: 8621\n ocr_text: 1623\n meetings: 3\n\n[+00m02s] ▶ Initialising tables, indexes, FTS\n creating tables ✓ 0m00s\n creating indexes ✓ 0m00s\n creating FTS tables ✓ 0m00s\n\n[+00m02s] ▶ Syncing data for 2026-04-28\n video_chunks ✓ 0m12s\n frames (4535 rows) ✓ 1m30s\n ocr_text (1623 rows) ✓ 0m32s\n ui_events (8621 rows) ✓ 0m01s\n elements (407532 rows) ✓ 1m02s\n meetings (3 rows) ✓ 0m00s\n\n[+03m19s] ▶ Updating FTS indexes\n elements_fts ✓ 1m36s\n frames_fts ✓ 2m28s\n ui_events_fts ✓ 0m04s\n\n[+07m27s] ▶ Verifying DB\n frames: 4535 / 4535 ✓\n elements: 407532 / 407532 ✓\n ui_events: 8621 / 8621 ✓\n ocr_text: 1623 / 1623 ✓\n meetings: 3 / 3 ✓\n\n[+08m59s] ▶ Copying data folder for 2026-04-28\n rsync 2026-04-28/ → NAS ✓ 0m20s (223 files, 159M)\n\n[2026-05-06 19:54:08] Archive DB size: 10G\n[2026-05-06 19:54:08] Total time: 9m19s\n[2026-05-06 19:54:08] Sync complete for 2026-04-28\n[2026-05-06 19:54:08] ========================================\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ pkill -f screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ rm -rf ~/.screenpipe/\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 92 lukas staff 2944 6 May 20:22 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd .npm \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ ll\ntotal 24\ndrwx------ 9 lukas staff 288 28 Apr 09:18 .\ndrwx------+ 92 lukas staff 2944 6 May 20:22 ..\ndrwx------ 5 lukas staff 160 1 Nov 2021 _cacache\ndrwx------@ 2 lukas staff 64 28 Apr 09:18 _locks\ndrwx------ 15 lukas staff 480 27 Apr 19:54 _logs\ndrwxr-xr-x 67 lukas staff 2144 28 Apr 09:17 _npx\n-rw-r--r--@ 1 lukas staff 0 26 Apr 19:10 _update-notifier-last-checked\n-rw-r--r-- 1 lukas staff 173 28 Apr 09:18 anonymous-cli-metrics.json\n-rw-r--r-- 1 lukas staff 4764 31 Jan 2024 eresolve-report.txt\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ rm -rf ~/.npm/_npx\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ ll \ntotal 52920\ndrwx------+ 92 lukas staff 2944 6 May 20:22 .\ndrwxr-xr-x 5 root admin 160 23 Aug 2024 ..\n-r-------- 1 lukas staff 7 18 Nov 2021 .CFUserTextEncoding\n-rw-r--r--@ 1 lukas staff 28676 27 Apr 09:11 .DS_Store\ndrwx------+ 10 lukas staff 320 28 Apr 17:07 .Trash\ndrwx------ 5 lukas staff 160 1 Nov 2021 .aws\n-rw-r--r-- 1 lukas staff 341470 29 Sep 2022 .babel.json\n-rw-------@ 1 lukas staff 388 25 Jul 2025 .bash_history\n-rw-r--r--@ 1 lukas staff 115 18 Apr 13:19 .bashrc\ndrwxr-xr-x 5 lukas staff 160 11 Mar 2023 .bito\ndrwx------@ 6 lukas staff 192 9 Apr 19:53 .cache\ndrwxr-xr-x 20 lukas staff 640 27 Apr 08:58 .claude\n-rw------- 1 lukas staff 28647 27 Apr 09:12 .claude.json\ndrwxr-xr-x@ 20 lukas staff 640 12 Mar 09:12 .codeium\ndrwxrwxrwx@ 3 lukas staff 96 2 Mar 2023 .composer\ndrwx------ 16 lukas staff 512 21 May 2025 .config\ndrwxr-xr-x 15 lukas staff 480 23 Dec 2024 .continue\ndrwx------@ 3 lukas staff 96 16 Feb 19:13 .copilot\ndrwxr-xr-x@ 5 lukas staff 160 9 Apr 2025 .cursor\ndrwxr-xr-x@ 5 lukas staff 160 17 Aug 2024 .cursor-tutor\ndrwxr-xr-x 3 lukas staff 96 8 Sep 2024 .daytona\ndrwxr-xr-x@ 4 lukas staff 128 18 Feb 10:52 .devdb\ndrwx------ 24 lukas staff 768 27 Apr 18:14 .docker\ndrwx------ 15 lukas staff 480 6 Jun 2023 .dropbox\ndrwxr-xr-x@ 3 lukas staff 96 20 Nov 2022 .fig.dotfiles.bak\n-rw-r--r-- 1 lukas staff 138 5 Mar 2022 .gauth\n-rw-r--r-- 1 lukas staff 220 25 Nov 2021 .gitconfig\n-rw-r--r-- 1 lukas staff 12288 25 Nov 2021 .gitconfig.swp\ndrwx------ 5 lukas staff 160 18 Nov 2021 .hammerspoon\ndrwxr-xr-x 3 lukas staff 96 21 Mar 2025 .idlerc\n-rw------- 1 lukas staff 20 28 Apr 16:51 .lesshst\ndrwx------ 5 lukas staff 160 23 Dec 2024 .local\n-rw------- 1 lukas staff 204 16 Mar 2024 .netrc\ndrwx------ 3 lukas staff 96 1 Nov 2021 .node-gyp\n-rw------- 1 lukas staff 4 6 Feb 2024 .node_repl_history\n-rw-r--r-- 1 lukas staff 17 24 Dec 2023 .notion-enhancer\ndrwxr-xr-x 4 lukas staff 128 12 Jul 2024 .notion-py\ndrwx------ 8 lukas staff 256 6 May 20:24 .npm\n-rw------- 1 lukas staff 74 20 May 2024 .npmrc\ndrwx------ 32 lukas staff 1024 25 Jul 2025 .nvm\ndrwxr-xr-x 4 lukas staff 128 5 Aug 2023 .postman\n-rw-r--r--@ 1 lukas staff 77 9 Feb 2023 .profile\n-rw-------@ 1 lukas staff 3153 21 Mar 2025 .python_history\ndrwx------ 2 lukas staff 64 15 Nov 2021 .quicktype-vscode\ndrwxr-xr-x@ 8 lukas staff 256 16 Feb 08:48 .redis-insight\ndrwxr-xr-x 4 lukas staff 128 4 Feb 09:35 .sonarlint\ndrwx------ 15 lukas staff 480 8 Aug 2025 .ssh\ndrwxr-xr-x@ 3 lukas staff 96 15 Aug 2025 .streamlit\ndrwx------ 6 lukas staff 192 17 Oct 2022 .swiftpm\n-rw------- 1 lukas staff 12143 27 Apr 14:58 .viminfo\ndrwx------ 5 lukas staff 160 19 Jun 2023 .vscode\ndrwxr-xr-x@ 3 lukas staff 96 20 Jan 2025 .warp\n UW PICO 5.09 New Buffer \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n [ Read 1 line ] \n^G Get Help ^O WriteOut ^R Read File ^Y Prev Pg ^K Cut Text ^C Cur Pos \n^X Exit ^J Justify ^W Where is ^V Next Pg ^U UnCut Text ^T To Spell \ndrwxr-xr-x 4 lukas staff 128 29 Apr 2023 .wdm\ndrwxr-xr-x@ 5 lukas staff 160 26 Jan 13:03 .windsurf\ndrwxr-xr-x 4 lukas staff 128 24 Mar 12:03 .yarn\n-rw-r--r-- 1 lukas staff 116 30 Mar 10:12 .yarnrc\n-rw-r--r-- 1 lukas staff 49518 21 Apr 09:09 .zcompdump\n-rw-r--r--@ 1 lukas staff 46758 2 Nov 2025 .zcompdump.Lukas-Kovaliks-MacBook-Pro-Jiminny.23381\n-rw-r--r--@ 1 lukas staff 6116 20 Apr 19:52 .zprofile\n-rw-r--r-- 1 lukas staff 1468 8 Apr 2022 .zprofile-copy\n-rw-r--r--@ 1 lukas staff 2900 15 Mar 2023 .zprofile.pysave\n-rw------- 1 lukas staff 1731 29 Jun 2022 .zprofile.save\n-rw-r--r-- 1 lukas staff 1569 8 Apr 2022 .zprofilees\n-rw------- 1 lukas staff 50310 28 Apr 11:32 .zsh_history\ndrwx------ 9 lukas staff 288 6 May 2025 .zsh_sessions\n-rw-r--r--@ 1 lukas staff 400 18 Apr 13:19 .zshrc\ndrwx------@ 9 lukas staff 288 20 Apr 20:55 Applications\ndrwxr-xr-x@ 2 lukas staff 64 22 Oct 2025 CascadeProjects\ndrwxr-xr-x 4 lukas staff 128 27 Oct 2025 DEV\ndrwx------@ 10 lukas staff 320 28 Apr 18:52 Desktop\ndrwx------@ 7 lukas staff 224 26 Mar 14:40 Documents\ndrwx------@ 44 lukas staff 1408 24 Apr 16:53 Downloads\ndrwxr-xr-x@ 4 lukas staff 128 17 Mar 20:27 Keychron_Screen\ndrwx------@ 112 lukas staff 3584 2 Dec 09:19 Library\ndrwx------ 7 lukas staff 224 12 Feb 2024 Movies\ndrwx------+ 5 lukas staff 160 25 Sep 2023 Music\ndrwx------+ 9 lukas staff 288 25 Sep 2023 Pictures\ndrwx------ 3 lukas staff 96 8 Nov 2021 Postman\ndrwx------+ 4 lukas staff 128 28 Oct 2021 Public\n-rw-r--r--@ 1 lukas staff 3950 15 Dec 09:16 Untitled 4.spf\ndrwx------ 4 lukas staff 128 2 Jul 2023 Users\n-rw-r--r-- 1 lukas staff 17050804 27 Apr 19:18 cleanshot-live.log\n-rw-r--r-- 1 lukas staff 9363061 27 Apr 19:24 cleanshot-screenpipe.log\n-rw-r--r-- 1 lukas staff 0 12 Apr 12:50 clip.mp4\n-rw-r--r-- 1 lukas staff 0 12 Apr 12:51 frame.jpg\ndrwx------ 3 lukas staff 96 30 Sep 2022 iCloud Drive (Archive)\ndrwx------ 16 lukas staff 512 3 Nov 2025 jiminny\ndrwxr-xr-x 3 lukas staff 96 20 Mar 18:47 node_modules\ndrwxr-xr-x 4 lukas staff 128 21 Oct 2025 raycast\n-rw-r--r-- 1 lukas staff 0 1 Mar 14:26 response.bin\n-rwxr-xr-x 1 lukas staff 3824 11 Apr 15:16 screenpipe-day.sh\n-rw-r--r-- 1 lukas staff 86 20 Mar 18:47 yarn.lock\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe\ncd: no such file or directory: /Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ touch screenpipe_sync.sh\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ nano screenpipe_sync.sh\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ npx screenpipe@latest record --ignored-windows \"Boosteroid\" --retention-days 7\ndetected hardware tier: Mid\nwarning: parakeet is not supported on this platform, using whisper-tiny instead\n2026-05-06T20:27:32.721416Z INFO screenpipe_engine::auth_key: api auth: key resolved via auto-generated\nchecking permissions...\n screen recording: ok\n microphone: ok\n accessibility: ok\n2026-05-06T20:27:32.831033Z INFO screenpipe_screen::monitor::macos_version: Detected macOS version: 14.6\n2026-05-06T20:27:34.088403Z INFO screenpipe_engine::sleep_monitor: Starting macOS sleep/wake monitor\n2026-05-06T20:27:34.089942Z INFO screenpipe_engine::sleep_monitor: Screen lock/unlock observers registered (CFNotificationCenter)\n2026-05-06T20:27:34.090417Z INFO screenpipe_engine::sleep_monitor: Display reconfiguration watcher registered (CGDisplayRegisterReconfigurationCallback)\n2026-05-06T20:27:34.112650Z INFO screenpipe_engine::permission_monitor: permission monitor started screen=true mic=true accessibility=true keychain=true\n2026-05-06T20:27:34.112711Z INFO screenpipe: meeting detector enabled — independent of transcription mode\n2026-05-06T20:27:34.619906Z INFO screenpipe: API server listening on 127.0.0.1:3030 (localhost only)\n2026-05-06T20:27:34.619937Z INFO screenpipe: API auth enabled — run `screenpipe auth token` to view your key\n2026-05-06T20:27:34.619857Z INFO screenpipe_engine::snapshot_compaction: snapshot compaction worker started (min_age=600s, poll=300s)\n2026-05-06T20:27:34.619847Z INFO screenpipe_engine::power::manager: power manager started (poll interval: 10s)\n2026-05-06T20:27:34.620018Z INFO screenpipe_engine::vision_manager::manager: Starting VisionManager\n2026-05-06T20:27:34.624746Z INFO screenpipe_core::pipes: installed built-in pipe: day-recap\n2026-05-06T20:27:34.626304Z INFO screenpipe_core::pipes: installed built-in pipe: standup-update\n2026-05-06T20:27:34.628597Z INFO screenpipe_core::pipes: installed built-in pipe: ai-habits\n2026-05-06T20:27:34.629463Z INFO screenpipe_core::pipes: installed built-in pipe: time-breakdown\n2026-05-06T20:27:34.630081Z INFO screenpipe_core::pipes: installed built-in pipe: video-export\n2026-05-06T20:27:34.630972Z INFO screenpipe_core::pipes: installed built-in pipe: meeting-summary\n2026-05-06T20:27:34.631427Z INFO screenpipe_core::pipes: loaded pipe: day-recap\n2026-05-06T20:27:34.631521Z INFO screenpipe_core::pipes: loaded pipe: standup-update\n2026-05-06T20:27:34.631587Z INFO screenpipe_core::pipes: loaded pipe: ai-habits\n2026-05-06T20:27:34.631640Z INFO screenpipe_core::pipes: loaded pipe: time-breakdown\n2026-05-06T20:27:34.631690Z INFO screenpipe_core::pipes: loaded pipe: video-export\n2026-05-06T20:27:34.631738Z INFO screenpipe_core::pipes: loaded pipe: meeting-summary\n2026-05-06T20:27:34.631752Z INFO screenpipe_core::pipes: loaded 6 pipes from \"/Users/lukas/.screenpipe/pipes\"\n\n\n\n _ \n __________________ ___ ____ ____ (_____ ___ \n / ___/ ___/ ___/ _ \\/ _ \\/ __ \\ / __ \\/ / __ \\/ _ \\\n (__ / /__/ / / __/ __/ / / / / /_/ / / /_/ / __/\n/____/\\___/_/ \\___/\\___/_/ /_/ / .___/_/ .___/\\___/ \n /_/ /_/ \n\n\n\npower AI by everything you've seen, said or heard\nopen source | runs locally | developer friendly\n\n\n┌────────────────────────┬────────────────────────────────────┐\n│ setting │ value │\n├────────────────────────┼────────────────────────────────────┤\n│ audio chunk duration │ 30 seconds │\n│ port │ 3030 │\n│ audio disabled │ false │\n│ vision disabled │ false │\n│ pause on DRM content │ false │\n│ audio engine │ Parakeet │\n│ vad engine │ Silero │\n│ data directory │ /Users/lukas/.screenpipe │\n│ debug mode │ false │\n│ telemetry │ true │\n│ use pii removal │ true │\n│ use all monitors │ true │\n│ ignored windows │ [\"Boosteroid\"] │\n│ included windows │ [] │\n│ cloud sync │ disabled │\n│ auto-destruct pid │ 0 │\n│ deepgram key │ not set │\n│ api auth │ enabled │\n│ encrypt secrets │ disabled │\n│ retention days │ 7 │\n│ retention mode │ media-only (keep transcripts) │\n├────────────────────────┼────────────────────────────────────┤\n│ languages │ │\n│ │ all languages │\n├────────────────────────┼────────────────────────────────────┤\n│ monitors │ │\n│ │ id: 1 │\n│ │ id: 2 │\n├────────────────────────┼────────────────────────────────────┤\n│ audio devices │ │\n│ │ MacBook Pro Microphone (input) │\n│ │ System Audio (output) │\n└────────────────────────┴────────────────────────────────────┘\nyou are using local processing. all your data stays on your computer.\n\nwarning: telemetry is enabled. only error-level data will be sent.\nto disable, use the --disable-telemetry flag.\n\ncheck latest changes here: https://github.com/screenpipe/screenpipe/releases\n2026-05-06T20:27:34.638384Z INFO screenpipe: starting UI event capture\n2026-05-06T20:27:34.637679Z INFO screenpipe_core::pipes: pipe scheduler started (generation 2)\n2026-05-06T20:27:34.649154Z INFO screenpipe_engine::power::manager: initial power profile: Performance (on_ac=true, battery=Some(94))\n2026-05-06T20:27:34.652794Z WARN screenpipe: pi agent install failed: bun not found — install from https://bun.sh\n2026-05-06T20:27:34.655839Z INFO screenpipe_engine::ui_recorder: Starting UI event capture\n2026-05-06T20:27:34.673877Z INFO screenpipe_engine::ui_recorder: UI recording session started: 54869993-7b4b-491f-b717-2a583517f9c5\n2026-05-06T20:27:34.673910Z INFO screenpipe_engine::calendar_speaker_id: speaker identification: started (user_name=<not set>)\n2026-05-06T20:27:34.674057Z INFO screenpipe_engine::hot_frame_cache: hot_frame_cache: warming from DB (2026-05-05 17:27:34.674056 UTC to 2026-05-06 17:27:34.674056 UTC)\n2026-05-06T20:27:34.674892Z INFO screenpipe_engine::meeting_detector: meeting v2: detection loop started (base_interval=5s, profiles=12)\n2026-05-06T20:27:34.675788Z INFO screenpipe_engine::hot_frame_cache: hot_frame_cache: warmed with 0 frame entries, coverage from 2026-05-05 17:27:34.674056 UTC\n2026-05-06T20:27:34.686546Z INFO screenpipe_engine::server: Server listening on 127.0.0.1:3030\n2026-05-06T20:27:34.691371Z INFO screenpipe_connect::mdns: mdns: advertising screenpipe on port 3030\n2026-05-06T20:27:36.270608Z INFO screenpipe_engine::vision_manager::manager: Starting vision recording for monitor 1 (1440x900)\n2026-05-06T20:27:36.270669Z INFO screenpipe_engine::vision_manager::manager: Starting event-driven capture for monitor 1 (device: monitor_1)\n2026-05-06T20:27:36.270714Z INFO screenpipe_engine::event_driven_capture: event-driven capture started for monitor 1 (device: monitor_1)\n2026-05-06T20:27:36.932583Z INFO screenpipe_engine::vision_manager::manager: Starting vision recording for monitor 2 (3008x1253)\n2026-05-06T20:27:36.932852Z INFO screenpipe_engine::vision_manager::manager: Starting event-driven capture for monitor 2 (device: monitor_2)\n2026-05-06T20:27:36.932882Z INFO screenpipe_engine::vision_manager::manager: VisionManager started with 2/2 monitor(s)\n2026-05-06T20:27:36.932899Z INFO screenpipe_engine::vision_manager::monitor_watcher: Starting monitor watcher (event-driven via CGDisplayRegisterReconfigurationCallback, 60s backstop poll)\n2026-05-06T20:27:36.932901Z INFO screenpipe_engine::event_driven_capture: event-driven capture started for monitor 2 (device: monitor_2)\n2026-05-06T20:27:39.158281Z INFO sck_rs::stream_manager: persistent SCK stream started for display 1 (1440x900, 2fps, 3 excluded)\n2026-05-06T20:27:39.593177Z INFO screenpipe_engine::event_driven_capture: startup capture for monitor 1: frame_id=1, dur=101ms\n2026-05-06T20:27:40.672366Z INFO sck_rs::stream_manager: persistent SCK stream started for display 2 (3008x1253, 2fps, 3 excluded)\n2026-05-06T20:27:41.257664Z INFO screenpipe_engine::event_driven_capture: startup capture for monitor 2: frame_id=2, dur=140ms\n2026-05-06T20:27:44.641022Z INFO screenpipe_audio::transcription::engine: whisper model available: \"/Users/lukas/.cache/huggingface/hub/models--ggerganov--whisper.cpp/snapshots/5359861c739e955e79d9a303bcbc70fb988958b1/ggml-tiny.bin\"\n2026-05-06T20:27:44.641079Z INFO screenpipe_audio::transcription::whisper::model: whisper context: gpu acceleration enabled (Metal on macOS, Vulkan on Windows)\n2026-05-06T20:27:44.641086Z INFO screenpipe_audio::transcription::engine: loading whisper model with GPU acceleration...\nwhisper_init_from_file_with_params_no_state: loading model from '/Users/lukas/.cache/huggingface/hub/models--ggerganov--whisper.cpp/snapshots/5359861c739e955e79d9a303bcbc70fb988958b1/ggml-tiny.bin'\nwhisper_init_with_params_no_state: use gpu = 1\nwhisper_init_with_params_no_state: flash attn = 0\nwhisper_init_with_params_no_state: gpu_device = 0\nwhisper_init_with_params_no_state: dtw = 0\nggml_metal_device_init: tensor API disabled for pre-M5 and pre-A19 devices\nggml_metal_library_init: using embedded metal library\nggml_metal_library_init: loaded in 0.041 sec\nggml_metal_rsets_init: creating a residency set collection (keep_alive = 180 s)\nggml_metal_device_init: GPU name: Apple M1\nggml_metal_device_init: GPU family: MTLGPUFamilyApple7 (1007)\nggml_metal_device_init: GPU family: MTLGPUFamilyCommon3 (3003)\nggml_metal_device_init: GPU family: MTLGPUFamilyMetal3 (5001)\nggml_metal_device_init: simdgroup reduction = true\nggml_metal_device_init: simdgroup matrix mul. = true\nggml_metal_device_init: has unified memory = true\nggml_metal_device_init: has bfloat = true\nggml_metal_device_init: has tensor = false\nggml_metal_device_init: use residency sets = true\nggml_metal_device_init: use shared buffers = true\nggml_metal_device_init: recommendedMaxWorkingSetSize = 11453.25 MB\nwhisper_init_with_params_no_state: devices = 3\nwhisper_init_with_params_no_state: backends = 3\nwhisper_model_load: loading model\nwhisper_model_load: n_vocab = 51865\nwhisper_model_load: n_audio_ctx = 1500\nwhisper_model_load: n_audio_state = 384\nwhisper_model_load: n_audio_head = 6\nwhisper_model_load: n_audio_layer = 4\nwhisper_model_load: n_text_ctx = 448\nwhisper_model_load: n_text_state = 384\nwhisper_model_load: n_text_head = 6\nwhisper_model_load: n_text_layer = 4\nwhisper_model_load: n_mels = 80\nwhisper_model_load: ftype = 1\nwhisper_model_load: qntvr = 0\nwhisper_model_load: type = 1 (tiny)\nwhisper_model_load: adding 1608 extra tokens\nwhisper_model_load: n_langs = 99\nwhisper_model_load: Metal total size = 77.11 MB\nwhisper_model_load: model size = 77.11 MB\n2026-05-06T20:27:44.857210Z INFO screenpipe_audio::transcription::engine: whisper model loaded successfully\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\n2026-05-06T20:27:44.861912Z INFO screenpipe_audio::audio_manager::manager: transcription session created (will be reused across segments)\n2026-05-06T20:27:44.862480Z INFO screenpipe_audio::audio_manager::manager: audio manager started\n2026-05-06T20:27:44.862525Z INFO screenpipe_audio::audio_manager::manager: calendar-assisted speaker diarization: listening for meeting events\n2026-05-06T20:27:47.831980Z INFO screenpipe_audio::device::device_manager: starting recording for device: System Audio (output)\n2026-05-06T20:27:47.832191Z INFO screenpipe_audio::core::run_record_and_transcribe: starting continuous recording for System Audio (output) (unknown / 30s segments)\n2026-05-06T20:27:47.906029Z INFO screenpipe_audio::device::device_manager: starting recording for device: MacBook Pro Microphone (input)\n2026-05-06T20:27:47.906090Z INFO screenpipe_audio::core::run_record_and_transcribe: starting continuous recording for MacBook Pro Microphone (input) (wired / 30s segments)\n2026-05-06T20:28:15.251258Z INFO screenpipe_engine::event_driven_capture: content dedup: skipping capture for monitor 1 (hash=-8608554010568040663, trigger=visual_change)\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\n2026-05-06T20:29:45.187551Z INFO screenpipe_audio::audio_manager::manager: reconciliation: transcribed 6 orphaned chunks\n2026-05-06T20:30:06.916244Z WARN screenpipe_audio::core::source_buffer: [MacBook Pro Microphone (input)] large gap on wired device: 81.4ms elapsed (expected 5.3ms) → inserting 76.0ms silence (7299 samples)\n2026-05-06T20:30:29.881247Z WARN screenpipe_audio::core::source_buffer: [MacBook Pro Microphone (input)] large gap on wired device: 96.0ms elapsed (expected 5.3ms) → inserting 90.7ms silence (8704 samples)\n^C2026-05-06T20:31:44.992913Z INFO screenpipe: received ctrl+c, initiating shutdown\n2026-05-06T20:31:44.993815Z INFO screenpipe_audio::device::device_manager: Stopping device: System Audio (output)\n2026-05-06T20:31:44.993845Z INFO screenpipe_audio::device::device_manager: Stopping device: System Audio (output)\n\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ 2026-05-06T20:31:45.865813Z INFO screenpipe_audio::device::device_manager: Stopping device: MacBook Pro Microphone (input)\n2026-05-06T20:31:45.865820Z INFO screenpipe_audio::device::device_manager: Stopping device: MacBook Pro Microphone (input)\n2026-05-06T20:31:45.892593Z INFO screenpipe_audio::audio_manager::manager: audio manager stopped\n2026-05-06T20:31:45.892684Z INFO screenpipe: stopping UI event capture\n2026-05-06T20:31:45.893002Z INFO screenpipe_engine::meeting_detector: meeting v2: shutdown received, exiting detection loop\n2026-05-06T20:31:45.893977Z INFO screenpipe: received shutdown signal for VisionManager\n2026-05-06T20:31:45.894556Z INFO screenpipe_engine::vision_manager::manager: Shutting down VisionManager\n2026-05-06T20:31:45.894516Z INFO screenpipe_engine::snapshot_compaction: snapshot compaction worker shutting down\n2026-05-06T20:31:45.894602Z INFO screenpipe_engine::vision_manager::manager: Stopping VisionManager\n2026-05-06T20:31:45.895419Z INFO screenpipe_engine::vision_manager::manager: Stopping vision recording for monitor 2\n2026-05-06T20:31:45.895898Z INFO screenpipe_engine::vision_manager::manager: Stopping vision recording for monitor 1\n2026-05-06T20:31:45.980559Z INFO screenpipe_engine::ui_recorder: UI recording session ended: 54869993-7b4b-491f-b717-2a583517f9c5\n2026-05-06T20:31:45.980777Z INFO screenpipe: shutdown complete\nggml_metal_free: deallocating\n2026-05-06T20:31:46.374234Z ERROR screenpipe_engine::event_driven_capture: event capture failed (trigger=click, monitor=1): monitor capture failed: capture task panicked: task 770 was cancelled\n\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ ;3B\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ sp-start\ndetected hardware tier: Mid\nwarning: parakeet is not supported on this platform, using whisper-tiny instead\n2026-05-06T20:32:21.850318Z INFO screenpipe_engine::auth_key: api auth: key resolved via secret store\nchecking permissions...\n screen recording: ok\n accessibility: ok\n2026-05-06T20:32:21.937393Z INFO screenpipe_screen::monitor::macos_version: Detected macOS version: 14.6\n2026-05-06T20:32:23.002257Z INFO screenpipe_engine::sleep_monitor: Starting macOS sleep/wake monitor\n2026-05-06T20:32:23.006683Z INFO screenpipe_engine::sleep_monitor: Screen lock/unlock observers registered (CFNotificationCenter)\n2026-05-06T20:32:23.008348Z INFO screenpipe_engine::sleep_monitor: Display reconfiguration watcher registered (CGDisplayRegisterReconfigurationCallback)\n2026-05-06T20:32:23.030912Z INFO screenpipe_engine::permission_monitor: permission monitor started screen=true mic=true accessibility=true keychain=true\n2026-05-06T20:32:23.030979Z INFO screenpipe: meeting detector enabled — independent of transcription mode\n2026-05-06T20:32:23.031261Z INFO screenpipe: API server listening on 127.0.0.1:3030 (localhost only)\n2026-05-06T20:32:23.031328Z INFO screenpipe_engine::vision_manager::manager: Starting VisionManager\n2026-05-06T20:32:23.031199Z INFO screenpipe_engine::snapshot_compaction: snapshot compaction worker started (min_age=600s, poll=300s)\n2026-05-06T20:32:23.031387Z INFO screenpipe: API auth enabled — run `screenpipe auth token` to view your key\n2026-05-06T20:32:23.031253Z INFO screenpipe_engine::power::manager: power manager started (poll interval: 10s)\n2026-05-06T20:32:23.034682Z INFO screenpipe_core::pipes: loaded pipe: day-recap\n2026-05-06T20:32:23.035042Z INFO screenpipe_core::pipes: loaded pipe: standup-update\n2026-05-06T20:32:23.035480Z INFO screenpipe_core::pipes: loaded pipe: ai-habits\n2026-05-06T20:32:23.035607Z INFO screenpipe_core::pipes: loaded pipe: time-breakdown\n2026-05-06T20:32:23.035705Z INFO screenpipe_core::pipes: loaded pipe: video-export\n2026-05-06T20:32:23.035815Z INFO screenpipe_core::pipes: loaded pipe: meeting-summary\n2026-05-06T20:32:23.035838Z INFO screenpipe_core::pipes: loaded 6 pipes from \"/Users/lukas/.screenpipe/pipes\"\n\n\n\n _ \n __________________ ___ ____ ____ (_____ ___ \n / ___/ ___/ ___/ _ \\/ _ \\/ __ \\ / __ \\/ / __ \\/ _ \\\n (__ / /__/ / / __/ __/ / / / / /_/ / / /_/ / __/\n/____/\\___/_/ \\___/\\___/_/ /_/ / .___/_/ .___/\\___/ \n /_/ /_/ \n\n\n\npower AI by everything you've seen, said or heard\nopen source | runs locally | developer friendly\n\n\n┌────────────────────────┬────────────────────────────────────┐\n│ setting │ value │\n├────────────────────────┼────────────────────────────────────┤\n│ audio chunk duration │ 30 seconds │\n│ port │ 3030 │\n│ audio disabled │ true │\n│ vision disabled │ false │\n│ pause on DRM content │ false │\n│ audio engine │ Parakeet │\n│ vad engine │ Silero │\n│ data directory │ /Users/lukas/.screenpipe │\n│ debug mode │ false │\n│ telemetry │ true │\n│ use pii removal │ true │\n│ use all monitors │ true │\n2026-05-06T20:32:23.037534Z INFO screenpipe_core::pipes: pipe scheduler started (generation 2)\n│ ignored windows │ [\"Boosteroid\"] │\n│ included windows │ [] │\n│ cloud sync │ disabled │\n│ auto-destruct pid │ 0 │\n│ deepgram key │ not set │\n│ api auth │ enabled │\n│ encrypt secrets │ disabled │\n│ retention days │ 14 │\n│ retention mode │ media-only (keep transcripts) │\n├────────────────────────┼────────────────────────────────────┤\n│ languages │ │\n│ │ all languages │\n├────────────────────────┼────────────────────────────────────┤\n│ monitors │ │\n│ │ id: 1 │\n│ │ id: 2 │\n├────────────────────────┼────────────────────────────────────┤\n│ audio devices │ │\n│ │ disabled │\n└────────────────────────┴────────────────────────────────────┘\nyou are using local processing. all your data stays on your computer.\n\nwarning: telemetry is enabled. only error-level data will be sent.\nto disable, use the --disable-telemetry flag.\n\ncheck latest changes here: https://github.com/screenpipe/screenpipe/releases\n2026-05-06T20:32:23.038046Z INFO screenpipe: starting UI event capture\n2026-05-06T20:32:23.058967Z WARN screenpipe: pi agent install failed: bun not found — install from https://bun.sh\n2026-05-06T20:32:23.060289Z INFO screenpipe_engine::power::manager: initial power profile: Performance (on_ac=true, battery=Some(95))\n2026-05-06T20:32:23.082491Z INFO screenpipe_engine::ui_recorder: Starting UI event capture\n2026-05-06T20:32:23.103681Z INFO screenpipe_engine::ui_recorder: UI recording session started: 83716bbd-ad71-45f9-9fba-e5b2bd8a5a97\n2026-05-06T20:32:23.103826Z INFO screenpipe_engine::calendar_speaker_id: speaker identification: started (user_name=<not set>)\n2026-05-06T20:32:23.103903Z INFO screenpipe_engine::hot_frame_cache: hot_frame_cache: warming from DB (2026-05-05 17:32:23.103901 UTC to 2026-05-06 17:32:23.103901 UTC)\n2026-05-06T20:32:23.107276Z INFO screenpipe_engine::meeting_detector: meeting v2: detection loop started (base_interval=5s, profiles=12)\n2026-05-06T20:32:23.116788Z INFO screenpipe_engine::server: Server listening on 127.0.0.1:3030\n2026-05-06T20:32:23.126899Z INFO screenpipe_connect::mdns: mdns: advertising screenpipe on port 3030\n2026-05-06T20:32:23.132524Z INFO screenpipe_engine::hot_frame_cache: hot_frame_cache: warmed with 52 frame entries, coverage from 2026-05-05 17:32:23.103901 UTC\n2026-05-06T20:32:24.842085Z INFO screenpipe_engine::vision_manager::manager: Starting vision recording for monitor 1 (1440x900)\n2026-05-06T20:32:24.842155Z INFO screenpipe_engine::vision_manager::manager: Starting event-driven capture for monitor 1 (device: monitor_1)\n2026-05-06T20:32:24.842202Z INFO screenpipe_engine::event_driven_capture: event-driven capture started for monitor 1 (device: monitor_1)\n2026-05-06T20:32:25.405285Z INFO screenpipe_engine::vision_manager::manager: Starting vision recording for monitor 2 (3008x1253)\n2026-05-06T20:32:25.405525Z INFO screenpipe_engine::vision_manager::manager: Starting event-driven capture for monitor 2 (device: monitor_2)\n2026-05-06T20:32:25.405604Z INFO screenpipe_engine::vision_manager::manager: VisionManager started with 2/2 monitor(s)\n2026-05-06T20:32:25.405641Z INFO screenpipe_engine::vision_manager::monitor_watcher: Starting monitor watcher (event-driven via CGDisplayRegisterReconfigurationCallback, 60s backstop poll)\n2026-05-06T20:32:25.405632Z INFO screenpipe_engine::event_driven_capture: event-driven capture started for monitor 2 (device: monitor_2)\n2026-05-06T20:32:27.627877Z INFO sck_rs::stream_manager: persistent SCK stream started for display 1 (1440x900, 2fps, 3 excluded)","is_focused":true},{"role":"AXTextField","text":"you","depth":3,"bounds":{"left":0.7888889,"top":0.10555556,"width":0.13055556,"height":0.024444444},"on_screen":true,"automation_id":"_NS:65","value":"you","role_description":"search text field","subrole":"AXSearchField","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"search","depth":4,"bounds":{"left":0.7902778,"top":0.10555556,"width":0.017361112,"height":0.024444444},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"cancel","depth":4,"bounds":{"left":0.9013889,"top":0.10555556,"width":0.015277778,"height":0.024444444},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"go left","depth":3,"bounds":{"left":0.925,"top":0.10666667,"width":0.014583333,"height":0.023333333},"on_screen":true,"automation_id":"_NS:59","role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"go right","depth":3,"bounds":{"left":0.93958336,"top":0.10666667,"width":0.014583333,"height":0.023333333},"on_screen":true,"automation_id":"_NS:49","role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXRadioButton","text":"DOCKER","depth":2,"bounds":{"left":0.0,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.004166667,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"DEV (docker)","depth":2,"bounds":{"left":0.16388889,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.16805555,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"APP (-zsh)","depth":2,"bounds":{"left":0.32777777,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.33194444,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.49166667,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.49583334,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"screenpipe\"","depth":2,"bounds":{"left":0.65555555,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.6597222,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.8194444,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.82361114,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"⌥⌘1","depth":1,"bounds":{"left":0.9548611,"top":0.032222223,"width":0.03888889,"height":0.018888889},"on_screen":true,"automation_id":"_NS:8","role_description":"text"},{"role":"AXStaticText","text":"screenpipe\"","depth":1,"bounds":{"left":0.47083333,"top":0.033333335,"width":0.058333334,"height":0.017777778},"on_screen":true,"role_description":"text"}]...
|
-2607752369936877213
|
4336429616147131745
|
manual
|
accessibility
|
NULL
|
rsync 2026-04-27/ → NAS ✓ 0m26s (242 f rsync 2026-04-27/ → NAS ✓ 0m26s (242 files, 325M)
[2026-05-06 19:41:28] Archive DB size: 9.7G
[2026-05-06 19:41:28] Total time: 19m12s
[2026-05-06 19:41:28] Sync complete for 2026-04-27
[2026-05-06 19:41:28] ========================================
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ~/.screenpipe/screenpipe_sync.sh 2026-04-28
[2026-05-06 19:44:49] ========================================
[2026-05-06 19:44:49] Screenpipe sync starting for: 2026-04-28
[2026-05-06 19:44:49] ========================================
[+00m00s] ▶ Preflight checks
Source DB: OK ( 11G)
NAS mount: OK /Volumes/screenpipe
Archive DB: exists (9.7G)
Data dir: OK (223 files, 159M)
[+00m00s] ▶ Counting source rows for 2026-04-28
frames: 4535
elements: 407532
ui_events: 8621
ocr_text: 1623
meetings: 3
[+00m02s] ▶ Initialising tables, indexes, FTS
creating tables ✓ 0m00s
creating indexes ✓ 0m00s
creating FTS tables ✓ 0m00s
[+00m02s] ▶ Syncing data for 2026-04-28
video_chunks ✓ 0m12s
frames (4535 rows) ✓ 1m30s
ocr_text (1623 rows) ✓ 0m32s
ui_events (8621 rows) ✓ 0m01s
elements (407532 rows) ✓ 1m02s
meetings (3 rows) ✓ 0m00s
[+03m19s] ▶ Updating FTS indexes
elements_fts ✓ 1m36s
frames_fts ✓ 2m28s
ui_events_fts ✓ 0m04s
[+07m27s] ▶ Verifying DB
frames: 4535 / 4535 ✓
elements: 407532 / 407532 ✓
ui_events: 8621 / 8621 ✓
ocr_text: 1623 / 1623 ✓
meetings: 3 / 3 ✓
[+08m59s] ▶ Copying data folder for 2026-04-28
rsync 2026-04-28/ → NAS ✓ 0m20s (223 files, 159M)
[2026-05-06 19:54:08] Archive DB size: 10G
[2026-05-06 19:54:08] Total time: 9m19s
[2026-05-06 19:54:08] Sync complete for 2026-04-28
[2026-05-06 19:54:08] ========================================
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ pkill -f screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ rm -rf ~/.screenpipe/
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 92 lukas staff 2944 6 May 20:22 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd .npm
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ ll
total 24
drwx------ 9 lukas staff 288 28 Apr 09:18 .
drwx------+ 92 lukas staff 2944 6 May 20:22 ..
drwx------ 5 lukas staff 160 1 Nov 2021 _cacache
drwx------@ 2 lukas staff 64 28 Apr 09:18 _locks
drwx------ 15 lukas staff 480 27 Apr 19:54 _logs
drwxr-xr-x 67 lukas staff 2144 28 Apr 09:17 _npx
-rw-r--r--@ 1 lukas staff 0 26 Apr 19:10 _update-notifier-last-checked
-rw-r--r-- 1 lukas staff 173 28 Apr 09:18 anonymous-cli-metrics.json
-rw-r--r-- 1 lukas staff 4764 31 Jan 2024 eresolve-report.txt
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ rm -rf ~/.npm/_npx
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ ll
total 52920
drwx------+ 92 lukas staff 2944 6 May 20:22 .
drwxr-xr-x 5 root admin 160 23 Aug 2024 ..
-r-------- 1 lukas staff 7 18 Nov 2021 .CFUserTextEncoding
-rw-r--r--@ 1 lukas staff 28676 27 Apr 09:11 .DS_Store
drwx------+ 10 lukas staff 320 28 Apr 17:07 .Trash
drwx------ 5 lukas staff 160 1 Nov 2021 .aws
-rw-r--r-- 1 lukas staff 341470 29 Sep 2022 .babel.json
-rw-------@ 1 lukas staff 388 25 Jul 2025 .bash_history
-rw-r--r--@ 1 lukas staff 115 18 Apr 13:19 .bashrc
drwxr-xr-x 5 lukas staff 160 11 Mar 2023 .bito
drwx------@ 6 lukas staff 192 9 Apr 19:53 .cache
drwxr-xr-x 20 lukas staff 640 27 Apr 08:58 .claude
-rw------- 1 lukas staff 28647 27 Apr 09:12 .claude.json
drwxr-xr-x@ 20 lukas staff 640 12 Mar 09:12 .codeium
drwxrwxrwx@ 3 lukas staff 96 2 Mar 2023 .composer
drwx------ 16 lukas staff 512 21 May 2025 .config
drwxr-xr-x 15 lukas staff 480 23 Dec 2024 .continue
drwx------@ 3 lukas staff 96 16 Feb 19:13 .copilot
drwxr-xr-x@ 5 lukas staff 160 9 Apr 2025 .cursor
drwxr-xr-x@ 5 lukas staff 160 17 Aug 2024 .cursor-tutor
drwxr-xr-x 3 lukas staff 96 8 Sep 2024 .daytona
drwxr-xr-x@ 4 lukas staff 128 18 Feb 10:52 .devdb
drwx------ 24 lukas staff 768 27 Apr 18:14 .docker
drwx------ 15 lukas staff 480 6 Jun 2023 .dropbox
drwxr-xr-x@ 3 lukas staff 96 20 Nov 2022 .fig.dotfiles.bak
-rw-r--r-- 1 lukas staff 138 5 Mar 2022 .gauth
-rw-r--r-- 1 lukas staff 220 25 Nov 2021 .gitconfig
-rw-r--r-- 1 lukas staff 12288 25 Nov 2021 .gitconfig.swp
drwx------ 5 lukas staff 160 18 Nov 2021 .hammerspoon
drwxr-xr-x 3 lukas staff 96 21 Mar 2025 .idlerc
-rw------- 1 lukas staff 20 28 Apr 16:51 .lesshst
drwx------ 5 lukas staff 160 23 Dec 2024 .local
-rw------- 1 lukas staff 204 16 Mar 2024 .netrc
drwx------ 3 lukas staff 96 1 Nov 2021 .node-gyp
-rw------- 1 lukas staff 4 6 Feb 2024 .node_repl_history
-rw-r--r-- 1 lukas staff 17 24 Dec 2023 .notion-enhancer
drwxr-xr-x 4 lukas staff 128 12 Jul 2024 .notion-py
drwx------ 8 lukas staff 256 6 May 20:24 .npm
-rw------- 1 lukas staff 74 20 May 2024 .npmrc
drwx------ 32 lukas staff 1024 25 Jul 2025 .nvm
drwxr-xr-x 4 lukas staff 128 5 Aug 2023 .postman
-rw-r--r--@ 1 lukas staff 77 9 Feb 2023 .profile
-rw-------@ 1 lukas staff 3153 21 Mar 2025 .python_history
drwx------ 2 lukas staff 64 15 Nov 2021 .quicktype-vscode
drwxr-xr-x@ 8 lukas staff 256 16 Feb 08:48 .redis-insight
drwxr-xr-x 4 lukas staff 128 4 Feb 09:35 .sonarlint
drwx------ 15 lukas staff 480 8 Aug 2025 .ssh
drwxr-xr-x@ 3 lukas staff 96 15 Aug 2025 .streamlit
drwx------ 6 lukas staff 192 17 Oct 2022 .swiftpm
-rw------- 1 lukas staff 12143 27 Apr 14:58 .viminfo
drwx------ 5 lukas staff 160 19 Jun 2023 .vscode
drwxr-xr-x@ 3 lukas staff 96 20 Jan 2025 .warp
UW PICO 5.09 New Buffer
[ Read 1 line ]
^G Get Help ^O WriteOut ^R Read File ^Y Prev Pg ^K Cut Text ^C Cur Pos
^X Exit ^J Justify ^W Where is ^V Next Pg ^U UnCut Text ^T To Spell
drwxr-xr-x 4 lukas staff 128 29 Apr 2023 .wdm
drwxr-xr-x@ 5 lukas staff 160 26 Jan 13:03 .windsurf
drwxr-xr-x 4 lukas staff 128 24 Mar 12:03 .yarn
-rw-r--r-- 1 lukas staff 116 30 Mar 10:12 .yarnrc
-rw-r--r-- 1 lukas staff 49518 21 Apr 09:09 .zcompdump
-rw-r--r--@ 1 lukas staff 46758 2 Nov 2025 .zcompdump.Lukas-Kovaliks-MacBook-Pro-Jiminny.23381
-rw-r--r--@ 1 lukas staff 6116 20 Apr 19:52 .zprofile
-rw-r--r-- 1 lukas staff 1468 8 Apr 2022 .zprofile-copy
-rw-r--r--@ 1 lukas staff 2900 15 Mar 2023 .zprofile.pysave
-rw------- 1 lukas staff 1731 29 Jun 2022 .zprofile.save
-rw-r--r-- 1 lukas staff 1569 8 Apr 2022 .zprofilees
-rw------- 1 lukas staff 50310 28 Apr 11:32 .zsh_history
drwx------ 9 lukas staff 288 6 May 2025 .zsh_sessions
-rw-r--r--@ 1 lukas staff 400 18 Apr 13:19 .zshrc
drwx------@ 9 lukas staff 288 20 Apr 20:55 Applications
drwxr-xr-x@ 2 lukas staff 64 22 Oct 2025 CascadeProjects
drwxr-xr-x 4 lukas staff 128 27 Oct 2025 DEV
drwx------@ 10 lukas staff 320 28 Apr 18:52 Desktop
drwx------@ 7 lukas staff 224 26 Mar 14:40 Documents
drwx------@ 44 lukas staff 1408 24 Apr 16:53 Downloads
drwxr-xr-x@ 4 lukas staff 128 17 Mar 20:27 Keychron_Screen
drwx------@ 112 lukas staff 3584 2 Dec 09:19 Library
drwx------ 7 lukas staff 224 12 Feb 2024 Movies
drwx------+ 5 lukas staff 160 25 Sep 2023 Music
drwx------+ 9 lukas staff 288 25 Sep 2023 Pictures
drwx------ 3 lukas staff 96 8 Nov 2021 Postman
drwx------+ 4 lukas staff 128 28 Oct 2021 Public
-rw-r--r--@ 1 lukas staff 3950 15 Dec 09:16 Untitled 4.spf
drwx------ 4 lukas staff 128 2 Jul 2023 Users
-rw-r--r-- 1 lukas staff 17050804 27 Apr 19:18 cleanshot-live.log
-rw-r--r-- 1 lukas staff 9363061 27 Apr 19:24 cleanshot-screenpipe.log
-rw-r--r-- 1 lukas staff 0 12 Apr 12:50 clip.mp4
-rw-r--r-- 1 lukas staff 0 12 Apr 12:51 frame.jpg
drwx------ 3 lukas staff 96 30 Sep 2022 iCloud Drive (Archive)
drwx------ 16 lukas staff 512 3 Nov 2025 jiminny
drwxr-xr-x 3 lukas staff 96 20 Mar 18:47 node_modules
drwxr-xr-x 4 lukas staff 128 21 Oct 2025 raycast
-rw-r--r-- 1 lukas staff 0 1 Mar 14:26 response.bin
-rwxr-xr-x 1 lukas staff 3824 11 Apr 15:16 screenpipe-day.sh
-rw-r--r-- 1 lukas staff 86 20 Mar 18:47 yarn.lock
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
cd: no such file or directory: /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ touch screenpipe_sync.sh
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ nano screenpipe_sync.sh
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ npx screenpipe@latest record --ignored-windows "Boosteroid" --retention-days 7
detected hardware tier: Mid
warning: parakeet is not supported on this platform, using whisper-tiny instead
2026-05-06T20:27:32.721416Z INFO screenpipe_engine::auth_key: api auth: key resolved via auto-generated
checking permissions...
screen recording: ok
microphone: ok
accessibility: ok
2026-05-06T20:27:32.831033Z INFO screenpipe_screen::monitor::macos_version: Detected macOS version: 14.6
2026-05-06T20:27:34.088403Z INFO screenpipe_engine::sleep_monitor: Starting macOS sleep/wake monitor
2026-05-06T20:27:34.089942Z INFO screenpipe_engine::sleep_monitor: Screen lock/unlock observers registered (CFNotificationCenter)
2026-05-06T20:27:34.090417Z INFO screenpipe_engine::sleep_monitor: Display reconfiguration watcher registered (CGDisplayRegisterReconfigurationCallback)
2026-05-06T20:27:34.112650Z INFO screenpipe_engine::permission_monitor: permission monitor started screen=true mic=true accessibility=true keychain=true
2026-05-06T20:27:34.112711Z INFO screenpipe: meeting detector enabled — independent of transcription mode
2026-05-06T20:27:34.619906Z INFO screenpipe: API server listening on [IP_ADDRESS]:3030 (localhost only)
2026-05-06T20:27:34.619937Z INFO screenpipe: API auth enabled — run `screenpipe auth token` to view your key
2026-05-06T20:27:34.619857Z INFO screenpipe_engine::snapshot_compaction: snapshot compaction worker started (min_age=600s, poll=300s)
2026-05-06T20:27:34.619847Z INFO screenpipe_engine::power::manager: power manager started (poll interval: 10s)
2026-05-06T20:27:34.620018Z INFO screenpipe_engine::vision_manager::manager: Starting VisionManager
2026-05-06T20:27:34.624746Z INFO screenpipe_core::pipes: installed built-in pipe: day-recap
2026-05-06T20:27:34.626304Z INFO screenpipe_core::pipes: installed built-in pipe: standup-update
2026-05-06T20:27:34.628597Z INFO screenpipe_core::pipes: installed built-in pipe: ai-habits
2026-05-06T20:27:34.629463Z INFO screenpipe_core::pipes: installed built-in pipe: time-breakdown
2026-05-06T20:27:34.630081Z INFO screenpipe_core::pipes: installed built-in pipe: video-export
2026-05-06T20:27:34.630972Z INFO screenpipe_core::pipes: installed built-in pipe: meeting-summary
2026-05-06T20:27:34.631427Z INFO screenpipe_core::pipes: loaded pipe: day-recap
2026-05-06T20:27:34.631521Z INFO screenpipe_core::pipes: loaded pipe: standup-update
2026-05-06T20:27:34.631587Z INFO screenpipe_core::pipes: loaded pipe: ai-habits
2026-05-06T20:27:34.631640Z INFO screenpipe_core::pipes: loaded pipe: time-breakdown
2026-05-06T20:27:34.631690Z INFO screenpipe_core::pipes: loaded pipe: video-export
2026-05-06T20:27:34.631738Z INFO screenpipe_core::pipes: loaded pipe: meeting-summary
2026-05-06T20:27:34.631752Z INFO screenpipe_core::pipes: loaded 6 pipes from "/Users/lukas/.screenpipe/pipes"
_
__________________ ___ ____ ____ (_____ ___
/ ___/ ___/ ___/ _ \/ _ \/ __ \ / __ \/ / __ \/ _ \
(__ / /__/ / / __/ __/ / / / / /_/ / / /_/ / __/
/____/\___/_/ \___/\___/_/ /_/ / .___/_/ .___/\___/
/_/ /_/
power AI by everything you've seen, said or heard
open source | runs locally | developer friendly
┌────────────────────────┬────────────────────────────────────┐
│ setting │ value │
├────────────────────────┼────────────────────────────────────┤
│ audio chunk duration │ 30 seconds │
│ port │ 3030 │
│ audio disabled │ false │
│ vision disabled │ false │
│ pause on DRM content │ false │
│ audio engine │ Parakeet │
│ vad engine │ Silero │
│ data directory │ /Users/lukas/.screenpipe │
│ debug mode │ false │
│ telemetry │ true │
│ use pii removal │ true │
│ use all monitors │ true │
│ ignored windows │ ["Boosteroid"] │
│ included windows │ [] │
│ cloud sync │ disabled │
│ auto-destruct pid │ 0 │
│ deepgram key │ not set │
│ api auth │ enabled │
│ encrypt secrets │ disabled │
│ retention days │ 7 │
│ retention mode │ media-only (keep transcripts) │
├────────────────────────┼────────────────────────────────────┤
│ languages │ │
│ │ all languages │
├────────────────────────┼────────────────────────────────────┤
│ monitors │ │
│ │ id: 1 │
│ │ id: 2 │
├────────────────────────┼────────────────────────────────────┤
│ audio devices │ │
│ │ MacBook Pro Microphone (input) │
│ │ System Audio (output) │
└────────────────────────┴────────────────────────────────────┘
you are using local processing. all your data stays on your computer.
warning: telemetry is enabled. only error-level data will be sent.
to disable, use the --disable-telemetry flag.
check latest changes here: [URL_WITH_CREDENTIALS] ~ $ 2026-05-06T20:31:45.865813Z INFO screenpipe_audio::device::device_manager: Stopping device: MacBook Pro Microphone (input)
2026-05-06T20:31:45.865820Z INFO screenpipe_audio::device::device_manager: Stopping device: MacBook Pro Microphone (input)
2026-05-06T20:31:45.892593Z INFO screenpipe_audio::audio_manager::manager: audio manager stopped
2026-05-06T20:31:45.892684Z INFO screenpipe: stopping UI event capture
2026-05-06T20:31:45.893002Z INFO screenpipe_engine::meeting_detector: meeting v2: shutdown received, exiting detection loop
2026-05-06T20:31:45.893977Z INFO screenpipe: received shutdown signal for VisionManager
2026-05-06T20:31:45.894556Z INFO screenpipe_engine::vision_manager::manager: Shutting down VisionManager
2026-05-06T20:31:45.894516Z INFO screenpipe_engine::snapshot_compaction: snapshot compaction worker shutting down
2026-05-06T20:31:45.894602Z INFO screenpipe_engine::vision_manager::manager: Stopping VisionManager
2026-05-06T20:31:45.895419Z INFO screenpipe_engine::vision_manager::manager: Stopping vision recording for monitor 2
2026-05-06T20:31:45.895898Z INFO screenpipe_engine::vision_manager::manager: Stopping vision recording for monitor 1
2026-05-06T20:31:45.980559Z INFO screenpipe_engine::ui_recorder: UI recording session ended: 54869993-7b4b-491f-b717-2a583517f9c5
2026-05-06T20:31:45.980777Z INFO screenpipe: shutdown complete
ggml_metal_free: deallocating
2026-05-06T20:31:46.374234Z ERROR screenpipe_engine::event_driven_capture: event capture failed (trigger=click, monitor=1): monitor capture failed: capture task panicked: task 770 was cancelled
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ ;3B
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ sp-start
detected hardware tier: Mid
warning: parakeet is not supported on this platform, using whisper-tiny instead
2026-05-06T20:32:21.850318Z INFO screenpipe_engine::auth_key: api auth: key resolved via secret store
checking permissions...
screen recording: ok
accessibility: ok
2026-05-06T20:32:21.937393Z INFO screenpipe_screen::monitor::macos_version: Detected macOS version: 14.6
2026-05-06T20:32:23.002257Z INFO screenpipe_engine::sleep_monitor: Starting macOS sleep/wake monitor
2026-05-06T20:32:23.006683Z INFO screenpipe_engine::sleep_monitor: Screen lock/unlock observers registered (CFNotificationCenter)
2026-05-06T20:32:23.008348Z INFO screenpipe_engine::sleep_monitor: Display reconfiguration watcher registered (CGDisplayRegisterReconfigurationCallback)
2026-05-06T20:32:23.030912Z INFO screenpipe_engine::permission_monitor: permission monitor started screen=true mic=true accessibility=true keychain=true
2026-05-06T20:32:23.030979Z INFO screenpipe: meeting detector enabled — independent of transcription mode
2026-05-06T20:32:23.031261Z INFO screenpipe: API server listening on [IP_ADDRESS]:3030 (localhost only)
2026-05-06T20:32:23.031328Z INFO screenpipe_engine::vision_manager::manager: Starting VisionManager
2026-05-06T20:32:23.031199Z INFO screenpipe_engine::snapshot_compaction: snapshot compaction worker started (min_age=600s, poll=300s)
2026-05-06T20:32:23.031387Z INFO screenpipe: API auth enabled — run `screenpipe auth token` to view your key
2026-05-06T20:32:23.031253Z INFO screenpipe_engine::power::manager: power manager started (poll interval: 10s)
2026-05-06T20:32:23.034682Z INFO screenpipe_core::pipes: loaded pipe: day-recap
2026-05-06T20:32:23.035042Z INFO screenpipe_core::pipes: loaded pipe: standup-update
2026-05-06T20:32:23.035480Z INFO screenpipe_core::pipes: loaded pipe: ai-habits
2026-05-06T20:32:23.035607Z INFO screenpipe_core::pipes: loaded pipe: time-breakdown
2026-05-06T20:32:23.035705Z INFO screenpipe_core::pipes: load...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
54
|
4
|
14
|
2026-05-06T17:32:25.907869+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778088745907_m2.jpg...
|
iTerm2
|
screenpipe"
|
True
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
[2026-05-06 19:41:28] Archive DB size: 9.7G
[2026 [2026-05-06 19:41:28] Archive DB size: 9.7G
[2026-05-06 19:41:28] Total time: 19m12s
[2026-05-06 19:41:28] Sync complete for 2026-04-27
[2026-05-06 19:41:28] ========================================
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ~/.screenpipe/screenpipe_sync.sh 2026-04-28
[2026-05-06 19:44:49] ========================================
[2026-05-06 19:44:49] Screenpipe sync starting for: 2026-04-28
[2026-05-06 19:44:49] ========================================
[+00m00s] ▶ Preflight checks
Source DB: OK ( 11G)
NAS mount: OK /Volumes/screenpipe
Archive DB: exists (9.7G)
Data dir: OK (223 files, 159M)
[+00m00s] ▶ Counting source rows for 2026-04-28
frames: 4535
elements: 407532
ui_events: 8621
ocr_text: 1623
meetings: 3
[+00m02s] ▶ Initialising tables, indexes, FTS
creating tables ✓ 0m00s
creating indexes ✓ 0m00s
creating FTS tables ✓ 0m00s
[+00m02s] ▶ Syncing data for 2026-04-28
video_chunks ✓ 0m12s
frames (4535 rows) ✓ 1m30s
ocr_text (1623 rows) ✓ 0m32s
ui_events (8621 rows) ✓ 0m01s
elements (407532 rows) ✓ 1m02s
meetings (3 rows) ✓ 0m00s
[+03m19s] ▶ Updating FTS indexes
elements_fts ✓ 1m36s
frames_fts ✓ 2m28s
ui_events_fts ✓ 0m04s
[+07m27s] ▶ Verifying DB
frames: 4535 / 4535 ✓
elements: 407532 / 407532 ✓
ui_events: 8621 / 8621 ✓
ocr_text: 1623 / 1623 ✓
meetings: 3 / 3 ✓
[+08m59s] ▶ Copying data folder for 2026-04-28
rsync 2026-04-28/ → NAS ✓ 0m20s (223 files, 159M)
[2026-05-06 19:54:08] Archive DB size: 10G
[2026-05-06 19:54:08] Total time: 9m19s
[2026-05-06 19:54:08] Sync complete for 2026-04-28
[2026-05-06 19:54:08] ========================================
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ pkill -f screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ rm -rf ~/.screenpipe/
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 92 lukas staff 2944 6 May 20:22 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd .npm
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ ll
total 24
drwx------ 9 lukas staff 288 28 Apr 09:18 .
drwx------+ 92 lukas staff 2944 6 May 20:22 ..
drwx------ 5 lukas staff 160 1 Nov 2021 _cacache
drwx------@ 2 lukas staff 64 28 Apr 09:18 _locks
drwx------ 15 lukas staff 480 27 Apr 19:54 _logs
drwxr-xr-x 67 lukas staff 2144 28 Apr 09:17 _npx
-rw-r--r--@ 1 lukas staff 0 26 Apr 19:10 _update-notifier-last-checked
-rw-r--r-- 1 lukas staff 173 28 Apr 09:18 anonymous-cli-metrics.json
-rw-r--r-- 1 lukas staff 4764 31 Jan 2024 eresolve-report.txt
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ rm -rf ~/.npm/_npx
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ ll
total 52920
drwx------+ 92 lukas staff 2944 6 May 20:22 .
drwxr-xr-x 5 root admin 160 23 Aug 2024 ..
-r-------- 1 lukas staff 7 18 Nov 2021 .CFUserTextEncoding
-rw-r--r--@ 1 lukas staff 28676 27 Apr 09:11 .DS_Store
drwx------+ 10 lukas staff 320 28 Apr 17:07 .Trash
drwx------ 5 lukas staff 160 1 Nov 2021 .aws
-rw-r--r-- 1 lukas staff 341470 29 Sep 2022 .babel.json
-rw-------@ 1 lukas staff 388 25 Jul 2025 .bash_history
-rw-r--r--@ 1 lukas staff 115 18 Apr 13:19 .bashrc
drwxr-xr-x 5 lukas staff 160 11 Mar 2023 .bito
drwx------@ 6 lukas staff 192 9 Apr 19:53 .cache
drwxr-xr-x 20 lukas staff 640 27 Apr 08:58 .claude
-rw------- 1 lukas staff 28647 27 Apr 09:12 .claude.json
drwxr-xr-x@ 20 lukas staff 640 12 Mar 09:12 .codeium
drwxrwxrwx@ 3 lukas staff 96 2 Mar 2023 .composer
drwx------ 16 lukas staff 512 21 May 2025 .config
drwxr-xr-x 15 lukas staff 480 23 Dec 2024 .continue
drwx------@ 3 lukas staff 96 16 Feb 19:13 .copilot
drwxr-xr-x@ 5 lukas staff 160 9 Apr 2025 .cursor
drwxr-xr-x@ 5 lukas staff 160 17 Aug 2024 .cursor-tutor
drwxr-xr-x 3 lukas staff 96 8 Sep 2024 .daytona
drwxr-xr-x@ 4 lukas staff 128 18 Feb 10:52 .devdb
drwx------ 24 lukas staff 768 27 Apr 18:14 .docker
drwx------ 15 lukas staff 480 6 Jun 2023 .dropbox
drwxr-xr-x@ 3 lukas staff 96 20 Nov 2022 .fig.dotfiles.bak
-rw-r--r-- 1 lukas staff 138 5 Mar 2022 .gauth
-rw-r--r-- 1 lukas staff 220 25 Nov 2021 .gitconfig
-rw-r--r-- 1 lukas staff 12288 25 Nov 2021 .gitconfig.swp
drwx------ 5 lukas staff 160 18 Nov 2021 .hammerspoon
drwxr-xr-x 3 lukas staff 96 21 Mar 2025 .idlerc
-rw------- 1 lukas staff 20 28 Apr 16:51 .lesshst
drwx------ 5 lukas staff 160 23 Dec 2024 .local
-rw------- 1 lukas staff 204 16 Mar 2024 .netrc
drwx------ 3 lukas staff 96 1 Nov 2021 .node-gyp
-rw------- 1 lukas staff 4 6 Feb 2024 .node_repl_history
-rw-r--r-- 1 lukas staff 17 24 Dec 2023 .notion-enhancer
drwxr-xr-x 4 lukas staff 128 12 Jul 2024 .notion-py
drwx------ 8 lukas staff 256 6 May 20:24 .npm
-rw------- 1 lukas staff 74 20 May 2024 .npmrc
drwx------ 32 lukas staff 1024 25 Jul 2025 .nvm
drwxr-xr-x 4 lukas staff 128 5 Aug 2023 .postman
-rw-r--r--@ 1 lukas staff 77 9 Feb 2023 .profile
-rw-------@ 1 lukas staff 3153 21 Mar 2025 .python_history
drwx------ 2 lukas staff 64 15 Nov 2021 .quicktype-vscode
drwxr-xr-x@ 8 lukas staff 256 16 Feb 08:48 .redis-insight
drwxr-xr-x 4 lukas staff 128 4 Feb 09:35 .sonarlint
drwx------ 15 lukas staff 480 8 Aug 2025 .ssh
drwxr-xr-x@ 3 lukas staff 96 15 Aug 2025 .streamlit
drwx------ 6 lukas staff 192 17 Oct 2022 .swiftpm
-rw------- 1 lukas staff 12143 27 Apr 14:58 .viminfo
drwx------ 5 lukas staff 160 19 Jun 2023 .vscode
drwxr-xr-x@ 3 lukas staff 96 20 Jan 2025 .warp
UW PICO 5.09 New Buffer
[ Read 1 line ]
^G Get Help ^O WriteOut ^R Read File ^Y Prev Pg ^K Cut Text ^C Cur Pos
^X Exit ^J Justify ^W Where is ^V Next Pg ^U UnCut Text ^T To Spell
drwxr-xr-x 4 lukas staff 128 29 Apr 2023 .wdm
drwxr-xr-x@ 5 lukas staff 160 26 Jan 13:03 .windsurf
drwxr-xr-x 4 lukas staff 128 24 Mar 12:03 .yarn
-rw-r--r-- 1 lukas staff 116 30 Mar 10:12 .yarnrc
-rw-r--r-- 1 lukas staff 49518 21 Apr 09:09 .zcompdump
-rw-r--r--@ 1 lukas staff 46758 2 Nov 2025 .zcompdump.Lukas-Kovaliks-MacBook-Pro-Jiminny.23381
-rw-r--r--@ 1 lukas staff 6116 20 Apr 19:52 .zprofile
-rw-r--r-- 1 lukas staff 1468 8 Apr 2022 .zprofile-copy
-rw-r--r--@ 1 lukas staff 2900 15 Mar 2023 .zprofile.pysave
-rw------- 1 lukas staff 1731 29 Jun 2022 .zprofile.save
-rw-r--r-- 1 lukas staff 1569 8 Apr 2022 .zprofilees
-rw------- 1 lukas staff 50310 28 Apr 11:32 .zsh_history
drwx------ 9 lukas staff 288 6 May 2025 .zsh_sessions
-rw-r--r--@ 1 lukas staff 400 18 Apr 13:19 .zshrc
drwx------@ 9 lukas staff 288 20 Apr 20:55 Applications
drwxr-xr-x@ 2 lukas staff 64 22 Oct 2025 CascadeProjects
drwxr-xr-x 4 lukas staff 128 27 Oct 2025 DEV
drwx------@ 10 lukas staff 320 28 Apr 18:52 Desktop
drwx------@ 7 lukas staff 224 26 Mar 14:40 Documents
drwx------@ 44 lukas staff 1408 24 Apr 16:53 Downloads
drwxr-xr-x@ 4 lukas staff 128 17 Mar 20:27 Keychron_Screen
drwx------@ 112 lukas staff 3584 2 Dec 09:19 Library
drwx------ 7 lukas staff 224 12 Feb 2024 Movies
drwx------+ 5 lukas staff 160 25 Sep 2023 Music
drwx------+ 9 lukas staff 288 25 Sep 2023 Pictures
drwx------ 3 lukas staff 96 8 Nov 2021 Postman
drwx------+ 4 lukas staff 128 28 Oct 2021 Public
-rw-r--r--@ 1 lukas staff 3950 15 Dec 09:16 Untitled 4.spf
drwx------ 4 lukas staff 128 2 Jul 2023 Users
-rw-r--r-- 1 lukas staff 17050804 27 Apr 19:18 cleanshot-live.log
-rw-r--r-- 1 lukas staff 9363061 27 Apr 19:24 cleanshot-screenpipe.log
-rw-r--r-- 1 lukas staff 0 12 Apr 12:50 clip.mp4
-rw-r--r-- 1 lukas staff 0 12 Apr 12:51 frame.jpg
drwx------ 3 lukas staff 96 30 Sep 2022 iCloud Drive (Archive)
drwx------ 16 lukas staff 512 3 Nov 2025 jiminny
drwxr-xr-x 3 lukas staff 96 20 Mar 18:47 node_modules
drwxr-xr-x 4 lukas staff 128 21 Oct 2025 raycast
-rw-r--r-- 1 lukas staff 0 1 Mar 14:26 response.bin
-rwxr-xr-x 1 lukas staff 3824 11 Apr 15:16 screenpipe-day.sh
-rw-r--r-- 1 lukas staff 86 20 Mar 18:47 yarn.lock
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
cd: no such file or directory: /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ touch screenpipe_sync.sh
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ nano screenpipe_sync.sh
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ npx screenpipe@latest record --ignored-windows "Boosteroid" --retention-days 7
detected hardware tier: Mid
warning: parakeet is not supported on this platform, using whisper-tiny instead
2026-05-06T20:27:32.721416Z INFO screenpipe_engine::auth_key: api auth: key resolved via auto-generated
checking permissions...
screen recording: ok
microphone: ok
accessibility: ok
2026-05-06T20:27:32.831033Z INFO screenpipe_screen::monitor::macos_version: Detected macOS version: 14.6
2026-05-06T20:27:34.088403Z INFO screenpipe_engine::sleep_monitor: Starting macOS sleep/wake monitor
2026-05-06T20:27:34.089942Z INFO screenpipe_engine::sleep_monitor: Screen lock/unlock observers registered (CFNotificationCenter)
2026-05-06T20:27:34.090417Z INFO screenpipe_engine::sleep_monitor: Display reconfiguration watcher registered (CGDisplayRegisterReconfigurationCallback)
2026-05-06T20:27:34.112650Z INFO screenpipe_engine::permission_monitor: permission monitor started screen=true mic=true accessibility=true keychain=true
2026-05-06T20:27:34.112711Z INFO screenpipe: meeting detector enabled — independent of transcription mode
2026-05-06T20:27:34.619906Z INFO screenpipe: API server listening on [IP_ADDRESS]:3030 (localhost only)
2026-05-06T20:27:34.619937Z INFO screenpipe: API auth enabled — run `screenpipe auth token` to view your key
2026-05-06T20:27:34.619857Z INFO screenpipe_engine::snapshot_compaction: snapshot compaction worker started (min_age=600s, poll=300s)
2026-05-06T20:27:34.619847Z INFO screenpipe_engine::power::manager: power manager started (poll interval: 10s)
2026-05-06T20:27:34.620018Z INFO screenpipe_engine::vision_manager::manager: Starting VisionManager
2026-05-06T20:27:34.624746Z INFO screenpipe_core::pipes: installed built-in pipe: day-recap
2026-05-06T20:27:34.626304Z INFO screenpipe_core::pipes: installed built-in pipe: standup-update
2026-05-06T20:27:34.628597Z INFO screenpipe_core::pipes: installed built-in pipe: ai-habits
2026-05-06T20:27:34.629463Z INFO screenpipe_core::pipes: installed built-in pipe: time-breakdown
2026-05-06T20:27:34.630081Z INFO screenpipe_core::pipes: installed built-in pipe: video-export
2026-05-06T20:27:34.630972Z INFO screenpipe_core::pipes: installed built-in pipe: meeting-summary
2026-05-06T20:27:34.631427Z INFO screenpipe_core::pipes: loaded pipe: day-recap
2026-05-06T20:27:34.631521Z INFO screenpipe_core::pipes: loaded pipe: standup-update
2026-05-06T20:27:34.631587Z INFO screenpipe_core::pipes: loaded pipe: ai-habits
2026-05-06T20:27:34.631640Z INFO screenpipe_core::pipes: loaded pipe: time-breakdown
2026-05-06T20:27:34.631690Z INFO screenpipe_core::pipes: loaded pipe: video-export
2026-05-06T20:27:34.631738Z INFO screenpipe_core::pipes: loaded pipe: meeting-summary
2026-05-06T20:27:34.631752Z INFO screenpipe_core::pipes: loaded 6 pipes from "/Users/lukas/.screenpipe/pipes"
_
__________________ ___ ____ ____ (_____ ___
/ ___/ ___/ ___/ _ \/ _ \/ __ \ / __ \/ / __ \/ _ \
(__ / /__/ / / __/ __/ / / / / /_/ / / /_/ / __/
/____/\___/_/ \___/\___/_/ /_/ / .___/_/ .___/\___/
/_/ /_/
power AI by everything you've seen, said or heard
open source | runs locally | developer friendly
┌────────────────────────┬────────────────────────────────────┐
│ setting │ value │
├────────────────────────┼────────────────────────────────────┤
│ audio chunk duration │ 30 seconds │
│ port │ 3030 │
│ audio disabled │ false │
│ vision disabled │ false │
│ pause on DRM content │ false │
│ audio engine │ Parakeet │
│ vad engine │ Silero │
│ data directory │ /Users/lukas/.screenpipe │
│ debug mode │ false │
│ telemetry │ true │
│ use pii removal │ true │
│ use all monitors │ true │
│ ignored windows │ ["Boosteroid"] │
│ included windows │ [] │
│ cloud sync │ disabled │
│ auto-destruct pid │ 0 │
│ deepgram key │ not set │
│ api auth │ enabled │
│ encrypt secrets │ disabled │
│ retention days │ 7 │
│ retention mode │ media-only (keep transcripts) │
├────────────────────────┼────────────────────────────────────┤
│ languages │ │
│ │ all languages │
├────────────────────────┼────────────────────────────────────┤
│ monitors │ │
│ │ id: 1 │
│ │ id: 2 │
├────────────────────────┼────────────────────────────────────┤
│ audio devices │ │
│ │ MacBook Pro Microphone (input) │
│ │ System Audio (output) │
└────────────────────────┴────────────────────────────────────┘
you are using local processing. all your data stays on your computer.
warning: telemetry is enabled. only error-level data will be sent.
to disable, use the --disable-telemetry flag.
check latest changes here: [URL_WITH_CREDENTIALS] ~ $ 2026-05-06T20:31:45.865813Z INFO screenpipe_audio::device::device_manager: Stopping device: MacBook Pro Microphone (input)
2026-05-06T20:31:45.865820Z INFO screenpipe_audio::device::device_manager: Stopping device: MacBook Pro Microphone (input)
2026-05-06T20:31:45.892593Z INFO screenpipe_audio::audio_manager::manager: audio manager stopped
2026-05-06T20:31:45.892684Z INFO screenpipe: stopping UI event capture
2026-05-06T20:31:45.893002Z INFO screenpipe_engine::meeting_detector: meeting v2: shutdown received, exiting detection loop
2026-05-06T20:31:45.893977Z INFO screenpipe: received shutdown signal for VisionManager
2026-05-06T20:31:45.894556Z INFO screenpipe_engine::vision_manager::manager: Shutting down VisionManager
2026-05-06T20:31:45.894516Z INFO screenpipe_engine::snapshot_compaction: snapshot compaction worker shutting down
2026-05-06T20:31:45.894602Z INFO screenpipe_engine::vision_manager::manager: Stopping VisionManager
2026-05-06T20:31:45.895419Z INFO screenpipe_engine::vision_manager::manager: Stopping vision recording for monitor 2
2026-05-06T20:31:45.895898Z INFO screenpipe_engine::vision_manager::manager: Stopping vision recording for monitor 1
2026-05-06T20:31:45.980559Z INFO screenpipe_engine::ui_recorder: UI recording session ended: 54869993-7b4b-491f-b717-2a583517f9c5
2026-05-06T20:31:45.980777Z INFO screenpipe: shutdown complete
ggml_metal_free: deallocating
2026-05-06T20:31:46.374234Z ERROR screenpipe_engine::event_driven_capture: event capture failed (trigger=click, monitor=1): monitor capture failed: capture task panicked: task 770 was cancelled
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ ;3B
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ sp-start
detected hardware tier: Mid
warning: parakeet is not supported on this platform, using whisper-tiny instead
2026-05-06T20:32:21.850318Z INFO screenpipe_engine::auth_key: api auth: key resolved via secret store
checking permissions...
screen recording: ok
accessibility: ok
2026-05-06T20:32:21.937393Z INFO screenpipe_screen::monitor::macos_version: Detected macOS version: 14.6
2026-05-06T20:32:23.002257Z INFO screenpipe_engine::sleep_monitor: Starting macOS sleep/wake monitor
2026-05-06T20:32:23.006683Z INFO screenpipe_engine::sleep_monitor: Screen lock/unlock observers registered (CFNotificationCenter)
2026-05-06T20:32:23.008348Z INFO screenpipe_engine::sleep_monitor: Display reconfiguration watcher registered (CGDisplayRegisterReconfigurationCallback)
2026-05-06T20:32:23.030912Z INFO screenpipe_engine::permission_monitor: permission monitor started screen=true mic=true accessibility=true keychain=true
2026-05-06T20:32:23.030979Z INFO screenpipe: meeting detector enabled — independent of transcription mode
2026-05-06T20:32:23.031261Z INFO screenpipe: API server listening on [IP_ADDRESS]:3030 (localhost only)
2026-05-06T20:32:23.031328Z INFO screenpipe_engine::vision_manager::manager: Starting VisionManager
2026-05-06T20:32:23.031199Z INFO screenpipe_engine::snapshot_compaction: snapshot compaction worker started (min_age=600s, poll=300s)
2026-05-06T20:32:23.031387Z INFO screenpipe: API auth enabled — run `screenpipe auth token` to view your key
2026-05-06T20:32:23.031253Z INFO screenpipe_engine::power::manager: power manager started (poll interval: 10s)
2026-05-06T20:32:23.034682Z INFO screenpipe_core::pipes: loaded pipe: day-recap
2026-05-06T20:32:23.035042Z INFO screenpipe_core::pipes: loaded pipe: standup-update
2026-05-06T20:32:23.035480Z INFO screenpipe_core::pipes: loaded pipe: ai-habits
2026-05-06T20:32:23.035607Z INFO screenpipe_core::pipes: loaded pipe: time-breakdown
2026-05-06T20:32:23.035705Z INFO screenpipe_core::pipes: loaded pipe: video-export
2026-05-06T20:32:23.035815Z INFO screenpipe_...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"[2026-05-06 19:41:28] Archive DB size: 9.7G\n[2026-05-06 19:41:28] Total time: 19m12s\n[2026-05-06 19:41:28] Sync complete for 2026-04-27\n[2026-05-06 19:41:28] ========================================\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ~/.screenpipe/screenpipe_sync.sh 2026-04-28\n[2026-05-06 19:44:49] ========================================\n[2026-05-06 19:44:49] Screenpipe sync starting for: 2026-04-28\n[2026-05-06 19:44:49] ========================================\n\n[+00m00s] ▶ Preflight checks\n Source DB: OK ( 11G)\n NAS mount: OK /Volumes/screenpipe\n Archive DB: exists (9.7G)\n Data dir: OK (223 files, 159M)\n\n[+00m00s] ▶ Counting source rows for 2026-04-28\n frames: 4535\n elements: 407532\n ui_events: 8621\n ocr_text: 1623\n meetings: 3\n\n[+00m02s] ▶ Initialising tables, indexes, FTS\n creating tables ✓ 0m00s\n creating indexes ✓ 0m00s\n creating FTS tables ✓ 0m00s\n\n[+00m02s] ▶ Syncing data for 2026-04-28\n video_chunks ✓ 0m12s\n frames (4535 rows) ✓ 1m30s\n ocr_text (1623 rows) ✓ 0m32s\n ui_events (8621 rows) ✓ 0m01s\n elements (407532 rows) ✓ 1m02s\n meetings (3 rows) ✓ 0m00s\n\n[+03m19s] ▶ Updating FTS indexes\n elements_fts ✓ 1m36s\n frames_fts ✓ 2m28s\n ui_events_fts ✓ 0m04s\n\n[+07m27s] ▶ Verifying DB\n frames: 4535 / 4535 ✓\n elements: 407532 / 407532 ✓\n ui_events: 8621 / 8621 ✓\n ocr_text: 1623 / 1623 ✓\n meetings: 3 / 3 ✓\n\n[+08m59s] ▶ Copying data folder for 2026-04-28\n rsync 2026-04-28/ → NAS ✓ 0m20s (223 files, 159M)\n\n[2026-05-06 19:54:08] Archive DB size: 10G\n[2026-05-06 19:54:08] Total time: 9m19s\n[2026-05-06 19:54:08] Sync complete for 2026-04-28\n[2026-05-06 19:54:08] ========================================\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ pkill -f screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ rm -rf ~/.screenpipe/\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 92 lukas staff 2944 6 May 20:22 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd .npm \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ ll\ntotal 24\ndrwx------ 9 lukas staff 288 28 Apr 09:18 .\ndrwx------+ 92 lukas staff 2944 6 May 20:22 ..\ndrwx------ 5 lukas staff 160 1 Nov 2021 _cacache\ndrwx------@ 2 lukas staff 64 28 Apr 09:18 _locks\ndrwx------ 15 lukas staff 480 27 Apr 19:54 _logs\ndrwxr-xr-x 67 lukas staff 2144 28 Apr 09:17 _npx\n-rw-r--r--@ 1 lukas staff 0 26 Apr 19:10 _update-notifier-last-checked\n-rw-r--r-- 1 lukas staff 173 28 Apr 09:18 anonymous-cli-metrics.json\n-rw-r--r-- 1 lukas staff 4764 31 Jan 2024 eresolve-report.txt\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ rm -rf ~/.npm/_npx\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ ll \ntotal 52920\ndrwx------+ 92 lukas staff 2944 6 May 20:22 .\ndrwxr-xr-x 5 root admin 160 23 Aug 2024 ..\n-r-------- 1 lukas staff 7 18 Nov 2021 .CFUserTextEncoding\n-rw-r--r--@ 1 lukas staff 28676 27 Apr 09:11 .DS_Store\ndrwx------+ 10 lukas staff 320 28 Apr 17:07 .Trash\ndrwx------ 5 lukas staff 160 1 Nov 2021 .aws\n-rw-r--r-- 1 lukas staff 341470 29 Sep 2022 .babel.json\n-rw-------@ 1 lukas staff 388 25 Jul 2025 .bash_history\n-rw-r--r--@ 1 lukas staff 115 18 Apr 13:19 .bashrc\ndrwxr-xr-x 5 lukas staff 160 11 Mar 2023 .bito\ndrwx------@ 6 lukas staff 192 9 Apr 19:53 .cache\ndrwxr-xr-x 20 lukas staff 640 27 Apr 08:58 .claude\n-rw------- 1 lukas staff 28647 27 Apr 09:12 .claude.json\ndrwxr-xr-x@ 20 lukas staff 640 12 Mar 09:12 .codeium\ndrwxrwxrwx@ 3 lukas staff 96 2 Mar 2023 .composer\ndrwx------ 16 lukas staff 512 21 May 2025 .config\ndrwxr-xr-x 15 lukas staff 480 23 Dec 2024 .continue\ndrwx------@ 3 lukas staff 96 16 Feb 19:13 .copilot\ndrwxr-xr-x@ 5 lukas staff 160 9 Apr 2025 .cursor\ndrwxr-xr-x@ 5 lukas staff 160 17 Aug 2024 .cursor-tutor\ndrwxr-xr-x 3 lukas staff 96 8 Sep 2024 .daytona\ndrwxr-xr-x@ 4 lukas staff 128 18 Feb 10:52 .devdb\ndrwx------ 24 lukas staff 768 27 Apr 18:14 .docker\ndrwx------ 15 lukas staff 480 6 Jun 2023 .dropbox\ndrwxr-xr-x@ 3 lukas staff 96 20 Nov 2022 .fig.dotfiles.bak\n-rw-r--r-- 1 lukas staff 138 5 Mar 2022 .gauth\n-rw-r--r-- 1 lukas staff 220 25 Nov 2021 .gitconfig\n-rw-r--r-- 1 lukas staff 12288 25 Nov 2021 .gitconfig.swp\ndrwx------ 5 lukas staff 160 18 Nov 2021 .hammerspoon\ndrwxr-xr-x 3 lukas staff 96 21 Mar 2025 .idlerc\n-rw------- 1 lukas staff 20 28 Apr 16:51 .lesshst\ndrwx------ 5 lukas staff 160 23 Dec 2024 .local\n-rw------- 1 lukas staff 204 16 Mar 2024 .netrc\ndrwx------ 3 lukas staff 96 1 Nov 2021 .node-gyp\n-rw------- 1 lukas staff 4 6 Feb 2024 .node_repl_history\n-rw-r--r-- 1 lukas staff 17 24 Dec 2023 .notion-enhancer\ndrwxr-xr-x 4 lukas staff 128 12 Jul 2024 .notion-py\ndrwx------ 8 lukas staff 256 6 May 20:24 .npm\n-rw------- 1 lukas staff 74 20 May 2024 .npmrc\ndrwx------ 32 lukas staff 1024 25 Jul 2025 .nvm\ndrwxr-xr-x 4 lukas staff 128 5 Aug 2023 .postman\n-rw-r--r--@ 1 lukas staff 77 9 Feb 2023 .profile\n-rw-------@ 1 lukas staff 3153 21 Mar 2025 .python_history\ndrwx------ 2 lukas staff 64 15 Nov 2021 .quicktype-vscode\ndrwxr-xr-x@ 8 lukas staff 256 16 Feb 08:48 .redis-insight\ndrwxr-xr-x 4 lukas staff 128 4 Feb 09:35 .sonarlint\ndrwx------ 15 lukas staff 480 8 Aug 2025 .ssh\ndrwxr-xr-x@ 3 lukas staff 96 15 Aug 2025 .streamlit\ndrwx------ 6 lukas staff 192 17 Oct 2022 .swiftpm\n-rw------- 1 lukas staff 12143 27 Apr 14:58 .viminfo\ndrwx------ 5 lukas staff 160 19 Jun 2023 .vscode\ndrwxr-xr-x@ 3 lukas staff 96 20 Jan 2025 .warp\n UW PICO 5.09 New Buffer \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n [ Read 1 line ] \n^G Get Help ^O WriteOut ^R Read File ^Y Prev Pg ^K Cut Text ^C Cur Pos \n^X Exit ^J Justify ^W Where is ^V Next Pg ^U UnCut Text ^T To Spell \ndrwxr-xr-x 4 lukas staff 128 29 Apr 2023 .wdm\ndrwxr-xr-x@ 5 lukas staff 160 26 Jan 13:03 .windsurf\ndrwxr-xr-x 4 lukas staff 128 24 Mar 12:03 .yarn\n-rw-r--r-- 1 lukas staff 116 30 Mar 10:12 .yarnrc\n-rw-r--r-- 1 lukas staff 49518 21 Apr 09:09 .zcompdump\n-rw-r--r--@ 1 lukas staff 46758 2 Nov 2025 .zcompdump.Lukas-Kovaliks-MacBook-Pro-Jiminny.23381\n-rw-r--r--@ 1 lukas staff 6116 20 Apr 19:52 .zprofile\n-rw-r--r-- 1 lukas staff 1468 8 Apr 2022 .zprofile-copy\n-rw-r--r--@ 1 lukas staff 2900 15 Mar 2023 .zprofile.pysave\n-rw------- 1 lukas staff 1731 29 Jun 2022 .zprofile.save\n-rw-r--r-- 1 lukas staff 1569 8 Apr 2022 .zprofilees\n-rw------- 1 lukas staff 50310 28 Apr 11:32 .zsh_history\ndrwx------ 9 lukas staff 288 6 May 2025 .zsh_sessions\n-rw-r--r--@ 1 lukas staff 400 18 Apr 13:19 .zshrc\ndrwx------@ 9 lukas staff 288 20 Apr 20:55 Applications\ndrwxr-xr-x@ 2 lukas staff 64 22 Oct 2025 CascadeProjects\ndrwxr-xr-x 4 lukas staff 128 27 Oct 2025 DEV\ndrwx------@ 10 lukas staff 320 28 Apr 18:52 Desktop\ndrwx------@ 7 lukas staff 224 26 Mar 14:40 Documents\ndrwx------@ 44 lukas staff 1408 24 Apr 16:53 Downloads\ndrwxr-xr-x@ 4 lukas staff 128 17 Mar 20:27 Keychron_Screen\ndrwx------@ 112 lukas staff 3584 2 Dec 09:19 Library\ndrwx------ 7 lukas staff 224 12 Feb 2024 Movies\ndrwx------+ 5 lukas staff 160 25 Sep 2023 Music\ndrwx------+ 9 lukas staff 288 25 Sep 2023 Pictures\ndrwx------ 3 lukas staff 96 8 Nov 2021 Postman\ndrwx------+ 4 lukas staff 128 28 Oct 2021 Public\n-rw-r--r--@ 1 lukas staff 3950 15 Dec 09:16 Untitled 4.spf\ndrwx------ 4 lukas staff 128 2 Jul 2023 Users\n-rw-r--r-- 1 lukas staff 17050804 27 Apr 19:18 cleanshot-live.log\n-rw-r--r-- 1 lukas staff 9363061 27 Apr 19:24 cleanshot-screenpipe.log\n-rw-r--r-- 1 lukas staff 0 12 Apr 12:50 clip.mp4\n-rw-r--r-- 1 lukas staff 0 12 Apr 12:51 frame.jpg\ndrwx------ 3 lukas staff 96 30 Sep 2022 iCloud Drive (Archive)\ndrwx------ 16 lukas staff 512 3 Nov 2025 jiminny\ndrwxr-xr-x 3 lukas staff 96 20 Mar 18:47 node_modules\ndrwxr-xr-x 4 lukas staff 128 21 Oct 2025 raycast\n-rw-r--r-- 1 lukas staff 0 1 Mar 14:26 response.bin\n-rwxr-xr-x 1 lukas staff 3824 11 Apr 15:16 screenpipe-day.sh\n-rw-r--r-- 1 lukas staff 86 20 Mar 18:47 yarn.lock\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe\ncd: no such file or directory: /Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ touch screenpipe_sync.sh\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ nano screenpipe_sync.sh\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ npx screenpipe@latest record --ignored-windows \"Boosteroid\" --retention-days 7\ndetected hardware tier: Mid\nwarning: parakeet is not supported on this platform, using whisper-tiny instead\n2026-05-06T20:27:32.721416Z INFO screenpipe_engine::auth_key: api auth: key resolved via auto-generated\nchecking permissions...\n screen recording: ok\n microphone: ok\n accessibility: ok\n2026-05-06T20:27:32.831033Z INFO screenpipe_screen::monitor::macos_version: Detected macOS version: 14.6\n2026-05-06T20:27:34.088403Z INFO screenpipe_engine::sleep_monitor: Starting macOS sleep/wake monitor\n2026-05-06T20:27:34.089942Z INFO screenpipe_engine::sleep_monitor: Screen lock/unlock observers registered (CFNotificationCenter)\n2026-05-06T20:27:34.090417Z INFO screenpipe_engine::sleep_monitor: Display reconfiguration watcher registered (CGDisplayRegisterReconfigurationCallback)\n2026-05-06T20:27:34.112650Z INFO screenpipe_engine::permission_monitor: permission monitor started screen=true mic=true accessibility=true keychain=true\n2026-05-06T20:27:34.112711Z INFO screenpipe: meeting detector enabled — independent of transcription mode\n2026-05-06T20:27:34.619906Z INFO screenpipe: API server listening on 127.0.0.1:3030 (localhost only)\n2026-05-06T20:27:34.619937Z INFO screenpipe: API auth enabled — run `screenpipe auth token` to view your key\n2026-05-06T20:27:34.619857Z INFO screenpipe_engine::snapshot_compaction: snapshot compaction worker started (min_age=600s, poll=300s)\n2026-05-06T20:27:34.619847Z INFO screenpipe_engine::power::manager: power manager started (poll interval: 10s)\n2026-05-06T20:27:34.620018Z INFO screenpipe_engine::vision_manager::manager: Starting VisionManager\n2026-05-06T20:27:34.624746Z INFO screenpipe_core::pipes: installed built-in pipe: day-recap\n2026-05-06T20:27:34.626304Z INFO screenpipe_core::pipes: installed built-in pipe: standup-update\n2026-05-06T20:27:34.628597Z INFO screenpipe_core::pipes: installed built-in pipe: ai-habits\n2026-05-06T20:27:34.629463Z INFO screenpipe_core::pipes: installed built-in pipe: time-breakdown\n2026-05-06T20:27:34.630081Z INFO screenpipe_core::pipes: installed built-in pipe: video-export\n2026-05-06T20:27:34.630972Z INFO screenpipe_core::pipes: installed built-in pipe: meeting-summary\n2026-05-06T20:27:34.631427Z INFO screenpipe_core::pipes: loaded pipe: day-recap\n2026-05-06T20:27:34.631521Z INFO screenpipe_core::pipes: loaded pipe: standup-update\n2026-05-06T20:27:34.631587Z INFO screenpipe_core::pipes: loaded pipe: ai-habits\n2026-05-06T20:27:34.631640Z INFO screenpipe_core::pipes: loaded pipe: time-breakdown\n2026-05-06T20:27:34.631690Z INFO screenpipe_core::pipes: loaded pipe: video-export\n2026-05-06T20:27:34.631738Z INFO screenpipe_core::pipes: loaded pipe: meeting-summary\n2026-05-06T20:27:34.631752Z INFO screenpipe_core::pipes: loaded 6 pipes from \"/Users/lukas/.screenpipe/pipes\"\n\n\n\n _ \n __________________ ___ ____ ____ (_____ ___ \n / ___/ ___/ ___/ _ \\/ _ \\/ __ \\ / __ \\/ / __ \\/ _ \\\n (__ / /__/ / / __/ __/ / / / / /_/ / / /_/ / __/\n/____/\\___/_/ \\___/\\___/_/ /_/ / .___/_/ .___/\\___/ \n /_/ /_/ \n\n\n\npower AI by everything you've seen, said or heard\nopen source | runs locally | developer friendly\n\n\n┌────────────────────────┬────────────────────────────────────┐\n│ setting │ value │\n├────────────────────────┼────────────────────────────────────┤\n│ audio chunk duration │ 30 seconds │\n│ port │ 3030 │\n│ audio disabled │ false │\n│ vision disabled │ false │\n│ pause on DRM content │ false │\n│ audio engine │ Parakeet │\n│ vad engine │ Silero │\n│ data directory │ /Users/lukas/.screenpipe │\n│ debug mode │ false │\n│ telemetry │ true │\n│ use pii removal │ true │\n│ use all monitors │ true │\n│ ignored windows │ [\"Boosteroid\"] │\n│ included windows │ [] │\n│ cloud sync │ disabled │\n│ auto-destruct pid │ 0 │\n│ deepgram key │ not set │\n│ api auth │ enabled │\n│ encrypt secrets │ disabled │\n│ retention days │ 7 │\n│ retention mode │ media-only (keep transcripts) │\n├────────────────────────┼────────────────────────────────────┤\n│ languages │ │\n│ │ all languages │\n├────────────────────────┼────────────────────────────────────┤\n│ monitors │ │\n│ │ id: 1 │\n│ │ id: 2 │\n├────────────────────────┼────────────────────────────────────┤\n│ audio devices │ │\n│ │ MacBook Pro Microphone (input) │\n│ │ System Audio (output) │\n└────────────────────────┴────────────────────────────────────┘\nyou are using local processing. all your data stays on your computer.\n\nwarning: telemetry is enabled. only error-level data will be sent.\nto disable, use the --disable-telemetry flag.\n\ncheck latest changes here: https://github.com/screenpipe/screenpipe/releases\n2026-05-06T20:27:34.638384Z INFO screenpipe: starting UI event capture\n2026-05-06T20:27:34.637679Z INFO screenpipe_core::pipes: pipe scheduler started (generation 2)\n2026-05-06T20:27:34.649154Z INFO screenpipe_engine::power::manager: initial power profile: Performance (on_ac=true, battery=Some(94))\n2026-05-06T20:27:34.652794Z WARN screenpipe: pi agent install failed: bun not found — install from https://bun.sh\n2026-05-06T20:27:34.655839Z INFO screenpipe_engine::ui_recorder: Starting UI event capture\n2026-05-06T20:27:34.673877Z INFO screenpipe_engine::ui_recorder: UI recording session started: 54869993-7b4b-491f-b717-2a583517f9c5\n2026-05-06T20:27:34.673910Z INFO screenpipe_engine::calendar_speaker_id: speaker identification: started (user_name=<not set>)\n2026-05-06T20:27:34.674057Z INFO screenpipe_engine::hot_frame_cache: hot_frame_cache: warming from DB (2026-05-05 17:27:34.674056 UTC to 2026-05-06 17:27:34.674056 UTC)\n2026-05-06T20:27:34.674892Z INFO screenpipe_engine::meeting_detector: meeting v2: detection loop started (base_interval=5s, profiles=12)\n2026-05-06T20:27:34.675788Z INFO screenpipe_engine::hot_frame_cache: hot_frame_cache: warmed with 0 frame entries, coverage from 2026-05-05 17:27:34.674056 UTC\n2026-05-06T20:27:34.686546Z INFO screenpipe_engine::server: Server listening on 127.0.0.1:3030\n2026-05-06T20:27:34.691371Z INFO screenpipe_connect::mdns: mdns: advertising screenpipe on port 3030\n2026-05-06T20:27:36.270608Z INFO screenpipe_engine::vision_manager::manager: Starting vision recording for monitor 1 (1440x900)\n2026-05-06T20:27:36.270669Z INFO screenpipe_engine::vision_manager::manager: Starting event-driven capture for monitor 1 (device: monitor_1)\n2026-05-06T20:27:36.270714Z INFO screenpipe_engine::event_driven_capture: event-driven capture started for monitor 1 (device: monitor_1)\n2026-05-06T20:27:36.932583Z INFO screenpipe_engine::vision_manager::manager: Starting vision recording for monitor 2 (3008x1253)\n2026-05-06T20:27:36.932852Z INFO screenpipe_engine::vision_manager::manager: Starting event-driven capture for monitor 2 (device: monitor_2)\n2026-05-06T20:27:36.932882Z INFO screenpipe_engine::vision_manager::manager: VisionManager started with 2/2 monitor(s)\n2026-05-06T20:27:36.932899Z INFO screenpipe_engine::vision_manager::monitor_watcher: Starting monitor watcher (event-driven via CGDisplayRegisterReconfigurationCallback, 60s backstop poll)\n2026-05-06T20:27:36.932901Z INFO screenpipe_engine::event_driven_capture: event-driven capture started for monitor 2 (device: monitor_2)\n2026-05-06T20:27:39.158281Z INFO sck_rs::stream_manager: persistent SCK stream started for display 1 (1440x900, 2fps, 3 excluded)\n2026-05-06T20:27:39.593177Z INFO screenpipe_engine::event_driven_capture: startup capture for monitor 1: frame_id=1, dur=101ms\n2026-05-06T20:27:40.672366Z INFO sck_rs::stream_manager: persistent SCK stream started for display 2 (3008x1253, 2fps, 3 excluded)\n2026-05-06T20:27:41.257664Z INFO screenpipe_engine::event_driven_capture: startup capture for monitor 2: frame_id=2, dur=140ms\n2026-05-06T20:27:44.641022Z INFO screenpipe_audio::transcription::engine: whisper model available: \"/Users/lukas/.cache/huggingface/hub/models--ggerganov--whisper.cpp/snapshots/5359861c739e955e79d9a303bcbc70fb988958b1/ggml-tiny.bin\"\n2026-05-06T20:27:44.641079Z INFO screenpipe_audio::transcription::whisper::model: whisper context: gpu acceleration enabled (Metal on macOS, Vulkan on Windows)\n2026-05-06T20:27:44.641086Z INFO screenpipe_audio::transcription::engine: loading whisper model with GPU acceleration...\nwhisper_init_from_file_with_params_no_state: loading model from '/Users/lukas/.cache/huggingface/hub/models--ggerganov--whisper.cpp/snapshots/5359861c739e955e79d9a303bcbc70fb988958b1/ggml-tiny.bin'\nwhisper_init_with_params_no_state: use gpu = 1\nwhisper_init_with_params_no_state: flash attn = 0\nwhisper_init_with_params_no_state: gpu_device = 0\nwhisper_init_with_params_no_state: dtw = 0\nggml_metal_device_init: tensor API disabled for pre-M5 and pre-A19 devices\nggml_metal_library_init: using embedded metal library\nggml_metal_library_init: loaded in 0.041 sec\nggml_metal_rsets_init: creating a residency set collection (keep_alive = 180 s)\nggml_metal_device_init: GPU name: Apple M1\nggml_metal_device_init: GPU family: MTLGPUFamilyApple7 (1007)\nggml_metal_device_init: GPU family: MTLGPUFamilyCommon3 (3003)\nggml_metal_device_init: GPU family: MTLGPUFamilyMetal3 (5001)\nggml_metal_device_init: simdgroup reduction = true\nggml_metal_device_init: simdgroup matrix mul. = true\nggml_metal_device_init: has unified memory = true\nggml_metal_device_init: has bfloat = true\nggml_metal_device_init: has tensor = false\nggml_metal_device_init: use residency sets = true\nggml_metal_device_init: use shared buffers = true\nggml_metal_device_init: recommendedMaxWorkingSetSize = 11453.25 MB\nwhisper_init_with_params_no_state: devices = 3\nwhisper_init_with_params_no_state: backends = 3\nwhisper_model_load: loading model\nwhisper_model_load: n_vocab = 51865\nwhisper_model_load: n_audio_ctx = 1500\nwhisper_model_load: n_audio_state = 384\nwhisper_model_load: n_audio_head = 6\nwhisper_model_load: n_audio_layer = 4\nwhisper_model_load: n_text_ctx = 448\nwhisper_model_load: n_text_state = 384\nwhisper_model_load: n_text_head = 6\nwhisper_model_load: n_text_layer = 4\nwhisper_model_load: n_mels = 80\nwhisper_model_load: ftype = 1\nwhisper_model_load: qntvr = 0\nwhisper_model_load: type = 1 (tiny)\nwhisper_model_load: adding 1608 extra tokens\nwhisper_model_load: n_langs = 99\nwhisper_model_load: Metal total size = 77.11 MB\nwhisper_model_load: model size = 77.11 MB\n2026-05-06T20:27:44.857210Z INFO screenpipe_audio::transcription::engine: whisper model loaded successfully\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\n2026-05-06T20:27:44.861912Z INFO screenpipe_audio::audio_manager::manager: transcription session created (will be reused across segments)\n2026-05-06T20:27:44.862480Z INFO screenpipe_audio::audio_manager::manager: audio manager started\n2026-05-06T20:27:44.862525Z INFO screenpipe_audio::audio_manager::manager: calendar-assisted speaker diarization: listening for meeting events\n2026-05-06T20:27:47.831980Z INFO screenpipe_audio::device::device_manager: starting recording for device: System Audio (output)\n2026-05-06T20:27:47.832191Z INFO screenpipe_audio::core::run_record_and_transcribe: starting continuous recording for System Audio (output) (unknown / 30s segments)\n2026-05-06T20:27:47.906029Z INFO screenpipe_audio::device::device_manager: starting recording for device: MacBook Pro Microphone (input)\n2026-05-06T20:27:47.906090Z INFO screenpipe_audio::core::run_record_and_transcribe: starting continuous recording for MacBook Pro Microphone (input) (wired / 30s segments)\n2026-05-06T20:28:15.251258Z INFO screenpipe_engine::event_driven_capture: content dedup: skipping capture for monitor 1 (hash=-8608554010568040663, trigger=visual_change)\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\n2026-05-06T20:29:45.187551Z INFO screenpipe_audio::audio_manager::manager: reconciliation: transcribed 6 orphaned chunks\n2026-05-06T20:30:06.916244Z WARN screenpipe_audio::core::source_buffer: [MacBook Pro Microphone (input)] large gap on wired device: 81.4ms elapsed (expected 5.3ms) → inserting 76.0ms silence (7299 samples)\n2026-05-06T20:30:29.881247Z WARN screenpipe_audio::core::source_buffer: [MacBook Pro Microphone (input)] large gap on wired device: 96.0ms elapsed (expected 5.3ms) → inserting 90.7ms silence (8704 samples)\n^C2026-05-06T20:31:44.992913Z INFO screenpipe: received ctrl+c, initiating shutdown\n2026-05-06T20:31:44.993815Z INFO screenpipe_audio::device::device_manager: Stopping device: System Audio (output)\n2026-05-06T20:31:44.993845Z INFO screenpipe_audio::device::device_manager: Stopping device: System Audio (output)\n\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ 2026-05-06T20:31:45.865813Z INFO screenpipe_audio::device::device_manager: Stopping device: MacBook Pro Microphone (input)\n2026-05-06T20:31:45.865820Z INFO screenpipe_audio::device::device_manager: Stopping device: MacBook Pro Microphone (input)\n2026-05-06T20:31:45.892593Z INFO screenpipe_audio::audio_manager::manager: audio manager stopped\n2026-05-06T20:31:45.892684Z INFO screenpipe: stopping UI event capture\n2026-05-06T20:31:45.893002Z INFO screenpipe_engine::meeting_detector: meeting v2: shutdown received, exiting detection loop\n2026-05-06T20:31:45.893977Z INFO screenpipe: received shutdown signal for VisionManager\n2026-05-06T20:31:45.894556Z INFO screenpipe_engine::vision_manager::manager: Shutting down VisionManager\n2026-05-06T20:31:45.894516Z INFO screenpipe_engine::snapshot_compaction: snapshot compaction worker shutting down\n2026-05-06T20:31:45.894602Z INFO screenpipe_engine::vision_manager::manager: Stopping VisionManager\n2026-05-06T20:31:45.895419Z INFO screenpipe_engine::vision_manager::manager: Stopping vision recording for monitor 2\n2026-05-06T20:31:45.895898Z INFO screenpipe_engine::vision_manager::manager: Stopping vision recording for monitor 1\n2026-05-06T20:31:45.980559Z INFO screenpipe_engine::ui_recorder: UI recording session ended: 54869993-7b4b-491f-b717-2a583517f9c5\n2026-05-06T20:31:45.980777Z INFO screenpipe: shutdown complete\nggml_metal_free: deallocating\n2026-05-06T20:31:46.374234Z ERROR screenpipe_engine::event_driven_capture: event capture failed (trigger=click, monitor=1): monitor capture failed: capture task panicked: task 770 was cancelled\n\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ ;3B\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ sp-start\ndetected hardware tier: Mid\nwarning: parakeet is not supported on this platform, using whisper-tiny instead\n2026-05-06T20:32:21.850318Z INFO screenpipe_engine::auth_key: api auth: key resolved via secret store\nchecking permissions...\n screen recording: ok\n accessibility: ok\n2026-05-06T20:32:21.937393Z INFO screenpipe_screen::monitor::macos_version: Detected macOS version: 14.6\n2026-05-06T20:32:23.002257Z INFO screenpipe_engine::sleep_monitor: Starting macOS sleep/wake monitor\n2026-05-06T20:32:23.006683Z INFO screenpipe_engine::sleep_monitor: Screen lock/unlock observers registered (CFNotificationCenter)\n2026-05-06T20:32:23.008348Z INFO screenpipe_engine::sleep_monitor: Display reconfiguration watcher registered (CGDisplayRegisterReconfigurationCallback)\n2026-05-06T20:32:23.030912Z INFO screenpipe_engine::permission_monitor: permission monitor started screen=true mic=true accessibility=true keychain=true\n2026-05-06T20:32:23.030979Z INFO screenpipe: meeting detector enabled — independent of transcription mode\n2026-05-06T20:32:23.031261Z INFO screenpipe: API server listening on 127.0.0.1:3030 (localhost only)\n2026-05-06T20:32:23.031328Z INFO screenpipe_engine::vision_manager::manager: Starting VisionManager\n2026-05-06T20:32:23.031199Z INFO screenpipe_engine::snapshot_compaction: snapshot compaction worker started (min_age=600s, poll=300s)\n2026-05-06T20:32:23.031387Z INFO screenpipe: API auth enabled — run `screenpipe auth token` to view your key\n2026-05-06T20:32:23.031253Z INFO screenpipe_engine::power::manager: power manager started (poll interval: 10s)\n2026-05-06T20:32:23.034682Z INFO screenpipe_core::pipes: loaded pipe: day-recap\n2026-05-06T20:32:23.035042Z INFO screenpipe_core::pipes: loaded pipe: standup-update\n2026-05-06T20:32:23.035480Z INFO screenpipe_core::pipes: loaded pipe: ai-habits\n2026-05-06T20:32:23.035607Z INFO screenpipe_core::pipes: loaded pipe: time-breakdown\n2026-05-06T20:32:23.035705Z INFO screenpipe_core::pipes: loaded pipe: video-export\n2026-05-06T20:32:23.035815Z INFO screenpipe_core::pipes: loaded pipe: meeting-summary\n2026-05-06T20:32:23.035838Z INFO screenpipe_core::pipes: loaded 6 pipes from \"/Users/lukas/.screenpipe/pipes\"\n\n\n\n _ \n __________________ ___ ____ ____ (_____ ___ \n / ___/ ___/ ___/ _ \\/ _ \\/ __ \\ / __ \\/ / __ \\/ _ \\\n (__ / /__/ / / __/ __/ / / / / /_/ / / /_/ / __/\n/____/\\___/_/ \\___/\\___/_/ /_/ / .___/_/ .___/\\___/ \n /_/ /_/ \n\n\n\npower AI by everything you've seen, said or heard\nopen source | runs locally | developer friendly\n\n\n┌────────────────────────┬────────────────────────────────────┐\n│ setting │ value │\n├────────────────────────┼────────────────────────────────────┤\n│ audio chunk duration │ 30 seconds │\n│ port │ 3030 │\n│ audio disabled │ true │\n│ vision disabled │ false │\n│ pause on DRM content │ false │\n│ audio engine │ Parakeet │\n│ vad engine │ Silero │\n│ data directory │ /Users/lukas/.screenpipe │\n│ debug mode │ false │\n│ telemetry │ true │\n│ use pii removal │ true │\n│ use all monitors │ true │\n2026-05-06T20:32:23.037534Z INFO screenpipe_core::pipes: pipe scheduler started (generation 2)\n│ ignored windows │ [\"Boosteroid\"] │\n│ included windows │ [] │\n│ cloud sync │ disabled │\n│ auto-destruct pid │ 0 │\n│ deepgram key │ not set │\n│ api auth │ enabled │\n│ encrypt secrets │ disabled │\n│ retention days │ 14 │\n│ retention mode │ media-only (keep transcripts) │\n├────────────────────────┼────────────────────────────────────┤\n│ languages │ │\n│ │ all languages │\n├────────────────────────┼────────────────────────────────────┤\n│ monitors │ │\n│ │ id: 1 │\n│ │ id: 2 │\n├────────────────────────┼────────────────────────────────────┤\n│ audio devices │ │\n│ │ disabled │\n└────────────────────────┴────────────────────────────────────┘\nyou are using local processing. all your data stays on your computer.\n\nwarning: telemetry is enabled. only error-level data will be sent.\nto disable, use the --disable-telemetry flag.\n\ncheck latest changes here: https://github.com/screenpipe/screenpipe/releases\n2026-05-06T20:32:23.038046Z INFO screenpipe: starting UI event capture\n2026-05-06T20:32:23.058967Z WARN screenpipe: pi agent install failed: bun not found — install from https://bun.sh\n2026-05-06T20:32:23.060289Z INFO screenpipe_engine::power::manager: initial power profile: Performance (on_ac=true, battery=Some(95))\n2026-05-06T20:32:23.082491Z INFO screenpipe_engine::ui_recorder: Starting UI event capture\n2026-05-06T20:32:23.103681Z INFO screenpipe_engine::ui_recorder: UI recording session started: 83716bbd-ad71-45f9-9fba-e5b2bd8a5a97\n2026-05-06T20:32:23.103826Z INFO screenpipe_engine::calendar_speaker_id: speaker identification: started (user_name=<not set>)\n2026-05-06T20:32:23.103903Z INFO screenpipe_engine::hot_frame_cache: hot_frame_cache: warming from DB (2026-05-05 17:32:23.103901 UTC to 2026-05-06 17:32:23.103901 UTC)\n2026-05-06T20:32:23.107276Z INFO screenpipe_engine::meeting_detector: meeting v2: detection loop started (base_interval=5s, profiles=12)\n2026-05-06T20:32:23.116788Z INFO screenpipe_engine::server: Server listening on 127.0.0.1:3030\n2026-05-06T20:32:23.126899Z INFO screenpipe_connect::mdns: mdns: advertising screenpipe on port 3030\n2026-05-06T20:32:23.132524Z INFO screenpipe_engine::hot_frame_cache: hot_frame_cache: warmed with 52 frame entries, coverage from 2026-05-05 17:32:23.103901 UTC\n2026-05-06T20:32:24.842085Z INFO screenpipe_engine::vision_manager::manager: Starting vision recording for monitor 1 (1440x900)\n2026-05-06T20:32:24.842155Z INFO screenpipe_engine::vision_manager::manager: Starting event-driven capture for monitor 1 (device: monitor_1)\n2026-05-06T20:32:24.842202Z INFO screenpipe_engine::event_driven_capture: event-driven capture started for monitor 1 (device: monitor_1)\n2026-05-06T20:32:25.405285Z INFO screenpipe_engine::vision_manager::manager: Starting vision recording for monitor 2 (3008x1253)\n2026-05-06T20:32:25.405525Z INFO screenpipe_engine::vision_manager::manager: Starting event-driven capture for monitor 2 (device: monitor_2)\n2026-05-06T20:32:25.405604Z INFO screenpipe_engine::vision_manager::manager: VisionManager started with 2/2 monitor(s)\n2026-05-06T20:32:25.405641Z INFO screenpipe_engine::vision_manager::monitor_watcher: Starting monitor watcher (event-driven via CGDisplayRegisterReconfigurationCallback, 60s backstop poll)\n2026-05-06T20:32:25.405632Z INFO screenpipe_engine::event_driven_capture: event-driven capture started for monitor 2 (device: monitor_2)\n2026-05-06T20:32:27.627877Z INFO sck_rs::stream_manager: persistent SCK stream started for display 1 (1440x900, 2fps, 3 excluded)\n2026-05-06T20:32:28.150868Z INFO screenpipe_engine::event_driven_capture: startup capture for monitor 1: frame_id=53, dur=82ms\n2026-05-06T20:32:28.853394Z INFO sck_rs::stream_manager: persistent SCK stream started for display 2 (3008x1253, 2fps, 3 excluded)","depth":4,"on_screen":true,"value":"[2026-05-06 19:41:28] Archive DB size: 9.7G\n[2026-05-06 19:41:28] Total time: 19m12s\n[2026-05-06 19:41:28] Sync complete for 2026-04-27\n[2026-05-06 19:41:28] ========================================\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ~/.screenpipe/screenpipe_sync.sh 2026-04-28\n[2026-05-06 19:44:49] ========================================\n[2026-05-06 19:44:49] Screenpipe sync starting for: 2026-04-28\n[2026-05-06 19:44:49] ========================================\n\n[+00m00s] ▶ Preflight checks\n Source DB: OK ( 11G)\n NAS mount: OK /Volumes/screenpipe\n Archive DB: exists (9.7G)\n Data dir: OK (223 files, 159M)\n\n[+00m00s] ▶ Counting source rows for 2026-04-28\n frames: 4535\n elements: 407532\n ui_events: 8621\n ocr_text: 1623\n meetings: 3\n\n[+00m02s] ▶ Initialising tables, indexes, FTS\n creating tables ✓ 0m00s\n creating indexes ✓ 0m00s\n creating FTS tables ✓ 0m00s\n\n[+00m02s] ▶ Syncing data for 2026-04-28\n video_chunks ✓ 0m12s\n frames (4535 rows) ✓ 1m30s\n ocr_text (1623 rows) ✓ 0m32s\n ui_events (8621 rows) ✓ 0m01s\n elements (407532 rows) ✓ 1m02s\n meetings (3 rows) ✓ 0m00s\n\n[+03m19s] ▶ Updating FTS indexes\n elements_fts ✓ 1m36s\n frames_fts ✓ 2m28s\n ui_events_fts ✓ 0m04s\n\n[+07m27s] ▶ Verifying DB\n frames: 4535 / 4535 ✓\n elements: 407532 / 407532 ✓\n ui_events: 8621 / 8621 ✓\n ocr_text: 1623 / 1623 ✓\n meetings: 3 / 3 ✓\n\n[+08m59s] ▶ Copying data folder for 2026-04-28\n rsync 2026-04-28/ → NAS ✓ 0m20s (223 files, 159M)\n\n[2026-05-06 19:54:08] Archive DB size: 10G\n[2026-05-06 19:54:08] Total time: 9m19s\n[2026-05-06 19:54:08] Sync complete for 2026-04-28\n[2026-05-06 19:54:08] ========================================\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ pkill -f screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ rm -rf ~/.screenpipe/\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 92 lukas staff 2944 6 May 20:22 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd .npm \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ ll\ntotal 24\ndrwx------ 9 lukas staff 288 28 Apr 09:18 .\ndrwx------+ 92 lukas staff 2944 6 May 20:22 ..\ndrwx------ 5 lukas staff 160 1 Nov 2021 _cacache\ndrwx------@ 2 lukas staff 64 28 Apr 09:18 _locks\ndrwx------ 15 lukas staff 480 27 Apr 19:54 _logs\ndrwxr-xr-x 67 lukas staff 2144 28 Apr 09:17 _npx\n-rw-r--r--@ 1 lukas staff 0 26 Apr 19:10 _update-notifier-last-checked\n-rw-r--r-- 1 lukas staff 173 28 Apr 09:18 anonymous-cli-metrics.json\n-rw-r--r-- 1 lukas staff 4764 31 Jan 2024 eresolve-report.txt\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ rm -rf ~/.npm/_npx\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ ll \ntotal 52920\ndrwx------+ 92 lukas staff 2944 6 May 20:22 .\ndrwxr-xr-x 5 root admin 160 23 Aug 2024 ..\n-r-------- 1 lukas staff 7 18 Nov 2021 .CFUserTextEncoding\n-rw-r--r--@ 1 lukas staff 28676 27 Apr 09:11 .DS_Store\ndrwx------+ 10 lukas staff 320 28 Apr 17:07 .Trash\ndrwx------ 5 lukas staff 160 1 Nov 2021 .aws\n-rw-r--r-- 1 lukas staff 341470 29 Sep 2022 .babel.json\n-rw-------@ 1 lukas staff 388 25 Jul 2025 .bash_history\n-rw-r--r--@ 1 lukas staff 115 18 Apr 13:19 .bashrc\ndrwxr-xr-x 5 lukas staff 160 11 Mar 2023 .bito\ndrwx------@ 6 lukas staff 192 9 Apr 19:53 .cache\ndrwxr-xr-x 20 lukas staff 640 27 Apr 08:58 .claude\n-rw------- 1 lukas staff 28647 27 Apr 09:12 .claude.json\ndrwxr-xr-x@ 20 lukas staff 640 12 Mar 09:12 .codeium\ndrwxrwxrwx@ 3 lukas staff 96 2 Mar 2023 .composer\ndrwx------ 16 lukas staff 512 21 May 2025 .config\ndrwxr-xr-x 15 lukas staff 480 23 Dec 2024 .continue\ndrwx------@ 3 lukas staff 96 16 Feb 19:13 .copilot\ndrwxr-xr-x@ 5 lukas staff 160 9 Apr 2025 .cursor\ndrwxr-xr-x@ 5 lukas staff 160 17 Aug 2024 .cursor-tutor\ndrwxr-xr-x 3 lukas staff 96 8 Sep 2024 .daytona\ndrwxr-xr-x@ 4 lukas staff 128 18 Feb 10:52 .devdb\ndrwx------ 24 lukas staff 768 27 Apr 18:14 .docker\ndrwx------ 15 lukas staff 480 6 Jun 2023 .dropbox\ndrwxr-xr-x@ 3 lukas staff 96 20 Nov 2022 .fig.dotfiles.bak\n-rw-r--r-- 1 lukas staff 138 5 Mar 2022 .gauth\n-rw-r--r-- 1 lukas staff 220 25 Nov 2021 .gitconfig\n-rw-r--r-- 1 lukas staff 12288 25 Nov 2021 .gitconfig.swp\ndrwx------ 5 lukas staff 160 18 Nov 2021 .hammerspoon\ndrwxr-xr-x 3 lukas staff 96 21 Mar 2025 .idlerc\n-rw------- 1 lukas staff 20 28 Apr 16:51 .lesshst\ndrwx------ 5 lukas staff 160 23 Dec 2024 .local\n-rw------- 1 lukas staff 204 16 Mar 2024 .netrc\ndrwx------ 3 lukas staff 96 1 Nov 2021 .node-gyp\n-rw------- 1 lukas staff 4 6 Feb 2024 .node_repl_history\n-rw-r--r-- 1 lukas staff 17 24 Dec 2023 .notion-enhancer\ndrwxr-xr-x 4 lukas staff 128 12 Jul 2024 .notion-py\ndrwx------ 8 lukas staff 256 6 May 20:24 .npm\n-rw------- 1 lukas staff 74 20 May 2024 .npmrc\ndrwx------ 32 lukas staff 1024 25 Jul 2025 .nvm\ndrwxr-xr-x 4 lukas staff 128 5 Aug 2023 .postman\n-rw-r--r--@ 1 lukas staff 77 9 Feb 2023 .profile\n-rw-------@ 1 lukas staff 3153 21 Mar 2025 .python_history\ndrwx------ 2 lukas staff 64 15 Nov 2021 .quicktype-vscode\ndrwxr-xr-x@ 8 lukas staff 256 16 Feb 08:48 .redis-insight\ndrwxr-xr-x 4 lukas staff 128 4 Feb 09:35 .sonarlint\ndrwx------ 15 lukas staff 480 8 Aug 2025 .ssh\ndrwxr-xr-x@ 3 lukas staff 96 15 Aug 2025 .streamlit\ndrwx------ 6 lukas staff 192 17 Oct 2022 .swiftpm\n-rw------- 1 lukas staff 12143 27 Apr 14:58 .viminfo\ndrwx------ 5 lukas staff 160 19 Jun 2023 .vscode\ndrwxr-xr-x@ 3 lukas staff 96 20 Jan 2025 .warp\n UW PICO 5.09 New Buffer \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n [ Read 1 line ] \n^G Get Help ^O WriteOut ^R Read File ^Y Prev Pg ^K Cut Text ^C Cur Pos \n^X Exit ^J Justify ^W Where is ^V Next Pg ^U UnCut Text ^T To Spell \ndrwxr-xr-x 4 lukas staff 128 29 Apr 2023 .wdm\ndrwxr-xr-x@ 5 lukas staff 160 26 Jan 13:03 .windsurf\ndrwxr-xr-x 4 lukas staff 128 24 Mar 12:03 .yarn\n-rw-r--r-- 1 lukas staff 116 30 Mar 10:12 .yarnrc\n-rw-r--r-- 1 lukas staff 49518 21 Apr 09:09 .zcompdump\n-rw-r--r--@ 1 lukas staff 46758 2 Nov 2025 .zcompdump.Lukas-Kovaliks-MacBook-Pro-Jiminny.23381\n-rw-r--r--@ 1 lukas staff 6116 20 Apr 19:52 .zprofile\n-rw-r--r-- 1 lukas staff 1468 8 Apr 2022 .zprofile-copy\n-rw-r--r--@ 1 lukas staff 2900 15 Mar 2023 .zprofile.pysave\n-rw------- 1 lukas staff 1731 29 Jun 2022 .zprofile.save\n-rw-r--r-- 1 lukas staff 1569 8 Apr 2022 .zprofilees\n-rw------- 1 lukas staff 50310 28 Apr 11:32 .zsh_history\ndrwx------ 9 lukas staff 288 6 May 2025 .zsh_sessions\n-rw-r--r--@ 1 lukas staff 400 18 Apr 13:19 .zshrc\ndrwx------@ 9 lukas staff 288 20 Apr 20:55 Applications\ndrwxr-xr-x@ 2 lukas staff 64 22 Oct 2025 CascadeProjects\ndrwxr-xr-x 4 lukas staff 128 27 Oct 2025 DEV\ndrwx------@ 10 lukas staff 320 28 Apr 18:52 Desktop\ndrwx------@ 7 lukas staff 224 26 Mar 14:40 Documents\ndrwx------@ 44 lukas staff 1408 24 Apr 16:53 Downloads\ndrwxr-xr-x@ 4 lukas staff 128 17 Mar 20:27 Keychron_Screen\ndrwx------@ 112 lukas staff 3584 2 Dec 09:19 Library\ndrwx------ 7 lukas staff 224 12 Feb 2024 Movies\ndrwx------+ 5 lukas staff 160 25 Sep 2023 Music\ndrwx------+ 9 lukas staff 288 25 Sep 2023 Pictures\ndrwx------ 3 lukas staff 96 8 Nov 2021 Postman\ndrwx------+ 4 lukas staff 128 28 Oct 2021 Public\n-rw-r--r--@ 1 lukas staff 3950 15 Dec 09:16 Untitled 4.spf\ndrwx------ 4 lukas staff 128 2 Jul 2023 Users\n-rw-r--r-- 1 lukas staff 17050804 27 Apr 19:18 cleanshot-live.log\n-rw-r--r-- 1 lukas staff 9363061 27 Apr 19:24 cleanshot-screenpipe.log\n-rw-r--r-- 1 lukas staff 0 12 Apr 12:50 clip.mp4\n-rw-r--r-- 1 lukas staff 0 12 Apr 12:51 frame.jpg\ndrwx------ 3 lukas staff 96 30 Sep 2022 iCloud Drive (Archive)\ndrwx------ 16 lukas staff 512 3 Nov 2025 jiminny\ndrwxr-xr-x 3 lukas staff 96 20 Mar 18:47 node_modules\ndrwxr-xr-x 4 lukas staff 128 21 Oct 2025 raycast\n-rw-r--r-- 1 lukas staff 0 1 Mar 14:26 response.bin\n-rwxr-xr-x 1 lukas staff 3824 11 Apr 15:16 screenpipe-day.sh\n-rw-r--r-- 1 lukas staff 86 20 Mar 18:47 yarn.lock\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe\ncd: no such file or directory: /Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ touch screenpipe_sync.sh\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ nano screenpipe_sync.sh\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ npx screenpipe@latest record --ignored-windows \"Boosteroid\" --retention-days 7\ndetected hardware tier: Mid\nwarning: parakeet is not supported on this platform, using whisper-tiny instead\n2026-05-06T20:27:32.721416Z INFO screenpipe_engine::auth_key: api auth: key resolved via auto-generated\nchecking permissions...\n screen recording: ok\n microphone: ok\n accessibility: ok\n2026-05-06T20:27:32.831033Z INFO screenpipe_screen::monitor::macos_version: Detected macOS version: 14.6\n2026-05-06T20:27:34.088403Z INFO screenpipe_engine::sleep_monitor: Starting macOS sleep/wake monitor\n2026-05-06T20:27:34.089942Z INFO screenpipe_engine::sleep_monitor: Screen lock/unlock observers registered (CFNotificationCenter)\n2026-05-06T20:27:34.090417Z INFO screenpipe_engine::sleep_monitor: Display reconfiguration watcher registered (CGDisplayRegisterReconfigurationCallback)\n2026-05-06T20:27:34.112650Z INFO screenpipe_engine::permission_monitor: permission monitor started screen=true mic=true accessibility=true keychain=true\n2026-05-06T20:27:34.112711Z INFO screenpipe: meeting detector enabled — independent of transcription mode\n2026-05-06T20:27:34.619906Z INFO screenpipe: API server listening on 127.0.0.1:3030 (localhost only)\n2026-05-06T20:27:34.619937Z INFO screenpipe: API auth enabled — run `screenpipe auth token` to view your key\n2026-05-06T20:27:34.619857Z INFO screenpipe_engine::snapshot_compaction: snapshot compaction worker started (min_age=600s, poll=300s)\n2026-05-06T20:27:34.619847Z INFO screenpipe_engine::power::manager: power manager started (poll interval: 10s)\n2026-05-06T20:27:34.620018Z INFO screenpipe_engine::vision_manager::manager: Starting VisionManager\n2026-05-06T20:27:34.624746Z INFO screenpipe_core::pipes: installed built-in pipe: day-recap\n2026-05-06T20:27:34.626304Z INFO screenpipe_core::pipes: installed built-in pipe: standup-update\n2026-05-06T20:27:34.628597Z INFO screenpipe_core::pipes: installed built-in pipe: ai-habits\n2026-05-06T20:27:34.629463Z INFO screenpipe_core::pipes: installed built-in pipe: time-breakdown\n2026-05-06T20:27:34.630081Z INFO screenpipe_core::pipes: installed built-in pipe: video-export\n2026-05-06T20:27:34.630972Z INFO screenpipe_core::pipes: installed built-in pipe: meeting-summary\n2026-05-06T20:27:34.631427Z INFO screenpipe_core::pipes: loaded pipe: day-recap\n2026-05-06T20:27:34.631521Z INFO screenpipe_core::pipes: loaded pipe: standup-update\n2026-05-06T20:27:34.631587Z INFO screenpipe_core::pipes: loaded pipe: ai-habits\n2026-05-06T20:27:34.631640Z INFO screenpipe_core::pipes: loaded pipe: time-breakdown\n2026-05-06T20:27:34.631690Z INFO screenpipe_core::pipes: loaded pipe: video-export\n2026-05-06T20:27:34.631738Z INFO screenpipe_core::pipes: loaded pipe: meeting-summary\n2026-05-06T20:27:34.631752Z INFO screenpipe_core::pipes: loaded 6 pipes from \"/Users/lukas/.screenpipe/pipes\"\n\n\n\n _ \n __________________ ___ ____ ____ (_____ ___ \n / ___/ ___/ ___/ _ \\/ _ \\/ __ \\ / __ \\/ / __ \\/ _ \\\n (__ / /__/ / / __/ __/ / / / / /_/ / / /_/ / __/\n/____/\\___/_/ \\___/\\___/_/ /_/ / .___/_/ .___/\\___/ \n /_/ /_/ \n\n\n\npower AI by everything you've seen, said or heard\nopen source | runs locally | developer friendly\n\n\n┌────────────────────────┬────────────────────────────────────┐\n│ setting │ value │\n├────────────────────────┼────────────────────────────────────┤\n│ audio chunk duration │ 30 seconds │\n│ port │ 3030 │\n│ audio disabled │ false │\n│ vision disabled │ false │\n│ pause on DRM content │ false │\n│ audio engine │ Parakeet │\n│ vad engine │ Silero │\n│ data directory │ /Users/lukas/.screenpipe │\n│ debug mode │ false │\n│ telemetry │ true │\n│ use pii removal │ true │\n│ use all monitors │ true │\n│ ignored windows │ [\"Boosteroid\"] │\n│ included windows │ [] │\n│ cloud sync │ disabled │\n│ auto-destruct pid │ 0 │\n│ deepgram key │ not set │\n│ api auth │ enabled │\n│ encrypt secrets │ disabled │\n│ retention days │ 7 │\n│ retention mode │ media-only (keep transcripts) │\n├────────────────────────┼────────────────────────────────────┤\n│ languages │ │\n│ │ all languages │\n├────────────────────────┼────────────────────────────────────┤\n│ monitors │ │\n│ │ id: 1 │\n│ │ id: 2 │\n├────────────────────────┼────────────────────────────────────┤\n│ audio devices │ │\n│ │ MacBook Pro Microphone (input) │\n│ │ System Audio (output) │\n└────────────────────────┴────────────────────────────────────┘\nyou are using local processing. all your data stays on your computer.\n\nwarning: telemetry is enabled. only error-level data will be sent.\nto disable, use the --disable-telemetry flag.\n\ncheck latest changes here: https://github.com/screenpipe/screenpipe/releases\n2026-05-06T20:27:34.638384Z INFO screenpipe: starting UI event capture\n2026-05-06T20:27:34.637679Z INFO screenpipe_core::pipes: pipe scheduler started (generation 2)\n2026-05-06T20:27:34.649154Z INFO screenpipe_engine::power::manager: initial power profile: Performance (on_ac=true, battery=Some(94))\n2026-05-06T20:27:34.652794Z WARN screenpipe: pi agent install failed: bun not found — install from https://bun.sh\n2026-05-06T20:27:34.655839Z INFO screenpipe_engine::ui_recorder: Starting UI event capture\n2026-05-06T20:27:34.673877Z INFO screenpipe_engine::ui_recorder: UI recording session started: 54869993-7b4b-491f-b717-2a583517f9c5\n2026-05-06T20:27:34.673910Z INFO screenpipe_engine::calendar_speaker_id: speaker identification: started (user_name=<not set>)\n2026-05-06T20:27:34.674057Z INFO screenpipe_engine::hot_frame_cache: hot_frame_cache: warming from DB (2026-05-05 17:27:34.674056 UTC to 2026-05-06 17:27:34.674056 UTC)\n2026-05-06T20:27:34.674892Z INFO screenpipe_engine::meeting_detector: meeting v2: detection loop started (base_interval=5s, profiles=12)\n2026-05-06T20:27:34.675788Z INFO screenpipe_engine::hot_frame_cache: hot_frame_cache: warmed with 0 frame entries, coverage from 2026-05-05 17:27:34.674056 UTC\n2026-05-06T20:27:34.686546Z INFO screenpipe_engine::server: Server listening on 127.0.0.1:3030\n2026-05-06T20:27:34.691371Z INFO screenpipe_connect::mdns: mdns: advertising screenpipe on port 3030\n2026-05-06T20:27:36.270608Z INFO screenpipe_engine::vision_manager::manager: Starting vision recording for monitor 1 (1440x900)\n2026-05-06T20:27:36.270669Z INFO screenpipe_engine::vision_manager::manager: Starting event-driven capture for monitor 1 (device: monitor_1)\n2026-05-06T20:27:36.270714Z INFO screenpipe_engine::event_driven_capture: event-driven capture started for monitor 1 (device: monitor_1)\n2026-05-06T20:27:36.932583Z INFO screenpipe_engine::vision_manager::manager: Starting vision recording for monitor 2 (3008x1253)\n2026-05-06T20:27:36.932852Z INFO screenpipe_engine::vision_manager::manager: Starting event-driven capture for monitor 2 (device: monitor_2)\n2026-05-06T20:27:36.932882Z INFO screenpipe_engine::vision_manager::manager: VisionManager started with 2/2 monitor(s)\n2026-05-06T20:27:36.932899Z INFO screenpipe_engine::vision_manager::monitor_watcher: Starting monitor watcher (event-driven via CGDisplayRegisterReconfigurationCallback, 60s backstop poll)\n2026-05-06T20:27:36.932901Z INFO screenpipe_engine::event_driven_capture: event-driven capture started for monitor 2 (device: monitor_2)\n2026-05-06T20:27:39.158281Z INFO sck_rs::stream_manager: persistent SCK stream started for display 1 (1440x900, 2fps, 3 excluded)\n2026-05-06T20:27:39.593177Z INFO screenpipe_engine::event_driven_capture: startup capture for monitor 1: frame_id=1, dur=101ms\n2026-05-06T20:27:40.672366Z INFO sck_rs::stream_manager: persistent SCK stream started for display 2 (3008x1253, 2fps, 3 excluded)\n2026-05-06T20:27:41.257664Z INFO screenpipe_engine::event_driven_capture: startup capture for monitor 2: frame_id=2, dur=140ms\n2026-05-06T20:27:44.641022Z INFO screenpipe_audio::transcription::engine: whisper model available: \"/Users/lukas/.cache/huggingface/hub/models--ggerganov--whisper.cpp/snapshots/5359861c739e955e79d9a303bcbc70fb988958b1/ggml-tiny.bin\"\n2026-05-06T20:27:44.641079Z INFO screenpipe_audio::transcription::whisper::model: whisper context: gpu acceleration enabled (Metal on macOS, Vulkan on Windows)\n2026-05-06T20:27:44.641086Z INFO screenpipe_audio::transcription::engine: loading whisper model with GPU acceleration...\nwhisper_init_from_file_with_params_no_state: loading model from '/Users/lukas/.cache/huggingface/hub/models--ggerganov--whisper.cpp/snapshots/5359861c739e955e79d9a303bcbc70fb988958b1/ggml-tiny.bin'\nwhisper_init_with_params_no_state: use gpu = 1\nwhisper_init_with_params_no_state: flash attn = 0\nwhisper_init_with_params_no_state: gpu_device = 0\nwhisper_init_with_params_no_state: dtw = 0\nggml_metal_device_init: tensor API disabled for pre-M5 and pre-A19 devices\nggml_metal_library_init: using embedded metal library\nggml_metal_library_init: loaded in 0.041 sec\nggml_metal_rsets_init: creating a residency set collection (keep_alive = 180 s)\nggml_metal_device_init: GPU name: Apple M1\nggml_metal_device_init: GPU family: MTLGPUFamilyApple7 (1007)\nggml_metal_device_init: GPU family: MTLGPUFamilyCommon3 (3003)\nggml_metal_device_init: GPU family: MTLGPUFamilyMetal3 (5001)\nggml_metal_device_init: simdgroup reduction = true\nggml_metal_device_init: simdgroup matrix mul. = true\nggml_metal_device_init: has unified memory = true\nggml_metal_device_init: has bfloat = true\nggml_metal_device_init: has tensor = false\nggml_metal_device_init: use residency sets = true\nggml_metal_device_init: use shared buffers = true\nggml_metal_device_init: recommendedMaxWorkingSetSize = 11453.25 MB\nwhisper_init_with_params_no_state: devices = 3\nwhisper_init_with_params_no_state: backends = 3\nwhisper_model_load: loading model\nwhisper_model_load: n_vocab = 51865\nwhisper_model_load: n_audio_ctx = 1500\nwhisper_model_load: n_audio_state = 384\nwhisper_model_load: n_audio_head = 6\nwhisper_model_load: n_audio_layer = 4\nwhisper_model_load: n_text_ctx = 448\nwhisper_model_load: n_text_state = 384\nwhisper_model_load: n_text_head = 6\nwhisper_model_load: n_text_layer = 4\nwhisper_model_load: n_mels = 80\nwhisper_model_load: ftype = 1\nwhisper_model_load: qntvr = 0\nwhisper_model_load: type = 1 (tiny)\nwhisper_model_load: adding 1608 extra tokens\nwhisper_model_load: n_langs = 99\nwhisper_model_load: Metal total size = 77.11 MB\nwhisper_model_load: model size = 77.11 MB\n2026-05-06T20:27:44.857210Z INFO screenpipe_audio::transcription::engine: whisper model loaded successfully\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\n2026-05-06T20:27:44.861912Z INFO screenpipe_audio::audio_manager::manager: transcription session created (will be reused across segments)\n2026-05-06T20:27:44.862480Z INFO screenpipe_audio::audio_manager::manager: audio manager started\n2026-05-06T20:27:44.862525Z INFO screenpipe_audio::audio_manager::manager: calendar-assisted speaker diarization: listening for meeting events\n2026-05-06T20:27:47.831980Z INFO screenpipe_audio::device::device_manager: starting recording for device: System Audio (output)\n2026-05-06T20:27:47.832191Z INFO screenpipe_audio::core::run_record_and_transcribe: starting continuous recording for System Audio (output) (unknown / 30s segments)\n2026-05-06T20:27:47.906029Z INFO screenpipe_audio::device::device_manager: starting recording for device: MacBook Pro Microphone (input)\n2026-05-06T20:27:47.906090Z INFO screenpipe_audio::core::run_record_and_transcribe: starting continuous recording for MacBook Pro Microphone (input) (wired / 30s segments)\n2026-05-06T20:28:15.251258Z INFO screenpipe_engine::event_driven_capture: content dedup: skipping capture for monitor 1 (hash=-8608554010568040663, trigger=visual_change)\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\nwhisper_backend_init_gpu: device 0: Metal (type: 1)\nwhisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)\nwhisper_backend_init_gpu: using Metal backend\nggml_metal_init: allocating\nggml_metal_init: found device: Apple M1\nggml_metal_init: picking default device: Apple M1\nggml_metal_init: use fusion = true\nggml_metal_init: use concurrency = true\nggml_metal_init: use graph optimize = true\nwhisper_backend_init: using BLAS backend\nwhisper_init_state: kv self size = 3.15 MB\nwhisper_init_state: kv cross size = 9.44 MB\nwhisper_init_state: kv pad size = 2.36 MB\nwhisper_init_state: compute buffer (conv) = 14.17 MB\nwhisper_init_state: compute buffer (encode) = 65.96 MB\nwhisper_init_state: compute buffer (cross) = 8.50 MB\nwhisper_init_state: compute buffer (decode) = 96.83 MB\nggml_metal_free: deallocating\n2026-05-06T20:29:45.187551Z INFO screenpipe_audio::audio_manager::manager: reconciliation: transcribed 6 orphaned chunks\n2026-05-06T20:30:06.916244Z WARN screenpipe_audio::core::source_buffer: [MacBook Pro Microphone (input)] large gap on wired device: 81.4ms elapsed (expected 5.3ms) → inserting 76.0ms silence (7299 samples)\n2026-05-06T20:30:29.881247Z WARN screenpipe_audio::core::source_buffer: [MacBook Pro Microphone (input)] large gap on wired device: 96.0ms elapsed (expected 5.3ms) → inserting 90.7ms silence (8704 samples)\n^C2026-05-06T20:31:44.992913Z INFO screenpipe: received ctrl+c, initiating shutdown\n2026-05-06T20:31:44.993815Z INFO screenpipe_audio::device::device_manager: Stopping device: System Audio (output)\n2026-05-06T20:31:44.993845Z INFO screenpipe_audio::device::device_manager: Stopping device: System Audio (output)\n\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ 2026-05-06T20:31:45.865813Z INFO screenpipe_audio::device::device_manager: Stopping device: MacBook Pro Microphone (input)\n2026-05-06T20:31:45.865820Z INFO screenpipe_audio::device::device_manager: Stopping device: MacBook Pro Microphone (input)\n2026-05-06T20:31:45.892593Z INFO screenpipe_audio::audio_manager::manager: audio manager stopped\n2026-05-06T20:31:45.892684Z INFO screenpipe: stopping UI event capture\n2026-05-06T20:31:45.893002Z INFO screenpipe_engine::meeting_detector: meeting v2: shutdown received, exiting detection loop\n2026-05-06T20:31:45.893977Z INFO screenpipe: received shutdown signal for VisionManager\n2026-05-06T20:31:45.894556Z INFO screenpipe_engine::vision_manager::manager: Shutting down VisionManager\n2026-05-06T20:31:45.894516Z INFO screenpipe_engine::snapshot_compaction: snapshot compaction worker shutting down\n2026-05-06T20:31:45.894602Z INFO screenpipe_engine::vision_manager::manager: Stopping VisionManager\n2026-05-06T20:31:45.895419Z INFO screenpipe_engine::vision_manager::manager: Stopping vision recording for monitor 2\n2026-05-06T20:31:45.895898Z INFO screenpipe_engine::vision_manager::manager: Stopping vision recording for monitor 1\n2026-05-06T20:31:45.980559Z INFO screenpipe_engine::ui_recorder: UI recording session ended: 54869993-7b4b-491f-b717-2a583517f9c5\n2026-05-06T20:31:45.980777Z INFO screenpipe: shutdown complete\nggml_metal_free: deallocating\n2026-05-06T20:31:46.374234Z ERROR screenpipe_engine::event_driven_capture: event capture failed (trigger=click, monitor=1): monitor capture failed: capture task panicked: task 770 was cancelled\n\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ ;3B\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ sp-start\ndetected hardware tier: Mid\nwarning: parakeet is not supported on this platform, using whisper-tiny instead\n2026-05-06T20:32:21.850318Z INFO screenpipe_engine::auth_key: api auth: key resolved via secret store\nchecking permissions...\n screen recording: ok\n accessibility: ok\n2026-05-06T20:32:21.937393Z INFO screenpipe_screen::monitor::macos_version: Detected macOS version: 14.6\n2026-05-06T20:32:23.002257Z INFO screenpipe_engine::sleep_monitor: Starting macOS sleep/wake monitor\n2026-05-06T20:32:23.006683Z INFO screenpipe_engine::sleep_monitor: Screen lock/unlock observers registered (CFNotificationCenter)\n2026-05-06T20:32:23.008348Z INFO screenpipe_engine::sleep_monitor: Display reconfiguration watcher registered (CGDisplayRegisterReconfigurationCallback)\n2026-05-06T20:32:23.030912Z INFO screenpipe_engine::permission_monitor: permission monitor started screen=true mic=true accessibility=true keychain=true\n2026-05-06T20:32:23.030979Z INFO screenpipe: meeting detector enabled — independent of transcription mode\n2026-05-06T20:32:23.031261Z INFO screenpipe: API server listening on 127.0.0.1:3030 (localhost only)\n2026-05-06T20:32:23.031328Z INFO screenpipe_engine::vision_manager::manager: Starting VisionManager\n2026-05-06T20:32:23.031199Z INFO screenpipe_engine::snapshot_compaction: snapshot compaction worker started (min_age=600s, poll=300s)\n2026-05-06T20:32:23.031387Z INFO screenpipe: API auth enabled — run `screenpipe auth token` to view your key\n2026-05-06T20:32:23.031253Z INFO screenpipe_engine::power::manager: power manager started (poll interval: 10s)\n2026-05-06T20:32:23.034682Z INFO screenpipe_core::pipes: loaded pipe: day-recap\n2026-05-06T20:32:23.035042Z INFO screenpipe_core::pipes: loaded pipe: standup-update\n2026-05-06T20:32:23.035480Z INFO screenpipe_core::pipes: loaded pipe: ai-habits\n2026-05-06T20:32:23.035607Z INFO screenpipe_core::pipes: loaded pipe: time-breakdown\n2026-05-06T20:32:23.035705Z INFO screenpipe_core::pipes: loaded pipe: video-export\n2026-05-06T20:32:23.035815Z INFO screenpipe_core::pipes: loaded pipe: meeting-summary\n2026-05-06T20:32:23.035838Z INFO screenpipe_core::pipes: loaded 6 pipes from \"/Users/lukas/.screenpipe/pipes\"\n\n\n\n _ \n __________________ ___ ____ ____ (_____ ___ \n / ___/ ___/ ___/ _ \\/ _ \\/ __ \\ / __ \\/ / __ \\/ _ \\\n (__ / /__/ / / __/ __/ / / / / /_/ / / /_/ / __/\n/____/\\___/_/ \\___/\\___/_/ /_/ / .___/_/ .___/\\___/ \n /_/ /_/ \n\n\n\npower AI by everything you've seen, said or heard\nopen source | runs locally | developer friendly\n\n\n┌────────────────────────┬────────────────────────────────────┐\n│ setting │ value │\n├────────────────────────┼────────────────────────────────────┤\n│ audio chunk duration │ 30 seconds │\n│ port │ 3030 │\n│ audio disabled │ true │\n│ vision disabled │ false │\n│ pause on DRM content │ false │\n│ audio engine │ Parakeet │\n│ vad engine │ Silero │\n│ data directory │ /Users/lukas/.screenpipe │\n│ debug mode │ false │\n│ telemetry │ true │\n│ use pii removal │ true │\n│ use all monitors │ true │\n2026-05-06T20:32:23.037534Z INFO screenpipe_core::pipes: pipe scheduler started (generation 2)\n│ ignored windows │ [\"Boosteroid\"] │\n│ included windows │ [] │\n│ cloud sync │ disabled │\n│ auto-destruct pid │ 0 │\n│ deepgram key │ not set │\n│ api auth │ enabled │\n│ encrypt secrets │ disabled │\n│ retention days │ 14 │\n│ retention mode │ media-only (keep transcripts) │\n├────────────────────────┼────────────────────────────────────┤\n│ languages │ │\n│ │ all languages │\n├────────────────────────┼────────────────────────────────────┤\n│ monitors │ │\n│ │ id: 1 │\n│ │ id: 2 │\n├────────────────────────┼────────────────────────────────────┤\n│ audio devices │ │\n│ │ disabled │\n└────────────────────────┴────────────────────────────────────┘\nyou are using local processing. all your data stays on your computer.\n\nwarning: telemetry is enabled. only error-level data will be sent.\nto disable, use the --disable-telemetry flag.\n\ncheck latest changes here: https://github.com/screenpipe/screenpipe/releases\n2026-05-06T20:32:23.038046Z INFO screenpipe: starting UI event capture\n2026-05-06T20:32:23.058967Z WARN screenpipe: pi agent install failed: bun not found — install from https://bun.sh\n2026-05-06T20:32:23.060289Z INFO screenpipe_engine::power::manager: initial power profile: Performance (on_ac=true, battery=Some(95))\n2026-05-06T20:32:23.082491Z INFO screenpipe_engine::ui_recorder: Starting UI event capture\n2026-05-06T20:32:23.103681Z INFO screenpipe_engine::ui_recorder: UI recording session started: 83716bbd-ad71-45f9-9fba-e5b2bd8a5a97\n2026-05-06T20:32:23.103826Z INFO screenpipe_engine::calendar_speaker_id: speaker identification: started (user_name=<not set>)\n2026-05-06T20:32:23.103903Z INFO screenpipe_engine::hot_frame_cache: hot_frame_cache: warming from DB (2026-05-05 17:32:23.103901 UTC to 2026-05-06 17:32:23.103901 UTC)\n2026-05-06T20:32:23.107276Z INFO screenpipe_engine::meeting_detector: meeting v2: detection loop started (base_interval=5s, profiles=12)\n2026-05-06T20:32:23.116788Z INFO screenpipe_engine::server: Server listening on 127.0.0.1:3030\n2026-05-06T20:32:23.126899Z INFO screenpipe_connect::mdns: mdns: advertising screenpipe on port 3030\n2026-05-06T20:32:23.132524Z INFO screenpipe_engine::hot_frame_cache: hot_frame_cache: warmed with 52 frame entries, coverage from 2026-05-05 17:32:23.103901 UTC\n2026-05-06T20:32:24.842085Z INFO screenpipe_engine::vision_manager::manager: Starting vision recording for monitor 1 (1440x900)\n2026-05-06T20:32:24.842155Z INFO screenpipe_engine::vision_manager::manager: Starting event-driven capture for monitor 1 (device: monitor_1)\n2026-05-06T20:32:24.842202Z INFO screenpipe_engine::event_driven_capture: event-driven capture started for monitor 1 (device: monitor_1)\n2026-05-06T20:32:25.405285Z INFO screenpipe_engine::vision_manager::manager: Starting vision recording for monitor 2 (3008x1253)\n2026-05-06T20:32:25.405525Z INFO screenpipe_engine::vision_manager::manager: Starting event-driven capture for monitor 2 (device: monitor_2)\n2026-05-06T20:32:25.405604Z INFO screenpipe_engine::vision_manager::manager: VisionManager started with 2/2 monitor(s)\n2026-05-06T20:32:25.405641Z INFO screenpipe_engine::vision_manager::monitor_watcher: Starting monitor watcher (event-driven via CGDisplayRegisterReconfigurationCallback, 60s backstop poll)\n2026-05-06T20:32:25.405632Z INFO screenpipe_engine::event_driven_capture: event-driven capture started for monitor 2 (device: monitor_2)\n2026-05-06T20:32:27.627877Z INFO sck_rs::stream_manager: persistent SCK stream started for display 1 (1440x900, 2fps, 3 excluded)\n2026-05-06T20:32:28.150868Z INFO screenpipe_engine::event_driven_capture: startup capture for monitor 1: frame_id=53, dur=82ms\n2026-05-06T20:32:28.853394Z INFO sck_rs::stream_manager: persistent SCK stream started for display 2 (3008x1253, 2fps, 3 excluded)","is_focused":true},{"role":"AXTextField","text":"you","depth":3,"bounds":{"left":0.64793885,"top":1.0,"width":0.0625,"height":-0.07581806},"on_screen":true,"automation_id":"_NS:65","value":"you","role_description":"search text field","subrole":"AXSearchField","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"search","depth":4,"bounds":{"left":0.64860374,"top":1.0,"width":0.00831117,"height":-0.07581806},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"cancel","depth":4,"bounds":{"left":0.7017952,"top":1.0,"width":0.00731383,"height":-0.07581806},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"go left","depth":3,"bounds":{"left":0.7130984,"top":1.0,"width":0.006981383,"height":-0.07661617},"on_screen":true,"automation_id":"_NS:59","role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"go right","depth":3,"bounds":{"left":0.7200798,"top":1.0,"width":0.006981383,"height":-0.07661617},"on_screen":true,"automation_id":"_NS:49","role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXRadioButton","text":"DOCKER","depth":2,"bounds":{"left":0.27027926,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.27227393,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"DEV (docker)","depth":2,"bounds":{"left":0.3487367,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.35073137,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"APP (-zsh)","depth":2,"bounds":{"left":0.42719415,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.42918882,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.5056516,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.50764626,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"screenpipe\"","depth":2,"bounds":{"left":0.58410907,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.58610374,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.6625665,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.66456115,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"⌥⌘1","depth":1,"bounds":{"left":0.7273936,"top":1.0,"width":0.01861702,"height":-0.023144484},"on_screen":true,"automation_id":"_NS:8","role_description":"text"},{"role":"AXStaticText","text":"screenpipe\"","depth":1,"bounds":{"left":0.4956782,"top":1.0,"width":0.027925532,"height":-0.02394259},"on_screen":true,"role_description":"text"}]...
|
-3153548874318014895
|
4336429617218774369
|
manual
|
accessibility
|
NULL
|
[2026-05-06 19:41:28] Archive DB size: 9.7G
[2026 [2026-05-06 19:41:28] Archive DB size: 9.7G
[2026-05-06 19:41:28] Total time: 19m12s
[2026-05-06 19:41:28] Sync complete for 2026-04-27
[2026-05-06 19:41:28] ========================================
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ~/.screenpipe/screenpipe_sync.sh 2026-04-28
[2026-05-06 19:44:49] ========================================
[2026-05-06 19:44:49] Screenpipe sync starting for: 2026-04-28
[2026-05-06 19:44:49] ========================================
[+00m00s] ▶ Preflight checks
Source DB: OK ( 11G)
NAS mount: OK /Volumes/screenpipe
Archive DB: exists (9.7G)
Data dir: OK (223 files, 159M)
[+00m00s] ▶ Counting source rows for 2026-04-28
frames: 4535
elements: 407532
ui_events: 8621
ocr_text: 1623
meetings: 3
[+00m02s] ▶ Initialising tables, indexes, FTS
creating tables ✓ 0m00s
creating indexes ✓ 0m00s
creating FTS tables ✓ 0m00s
[+00m02s] ▶ Syncing data for 2026-04-28
video_chunks ✓ 0m12s
frames (4535 rows) ✓ 1m30s
ocr_text (1623 rows) ✓ 0m32s
ui_events (8621 rows) ✓ 0m01s
elements (407532 rows) ✓ 1m02s
meetings (3 rows) ✓ 0m00s
[+03m19s] ▶ Updating FTS indexes
elements_fts ✓ 1m36s
frames_fts ✓ 2m28s
ui_events_fts ✓ 0m04s
[+07m27s] ▶ Verifying DB
frames: 4535 / 4535 ✓
elements: 407532 / 407532 ✓
ui_events: 8621 / 8621 ✓
ocr_text: 1623 / 1623 ✓
meetings: 3 / 3 ✓
[+08m59s] ▶ Copying data folder for 2026-04-28
rsync 2026-04-28/ → NAS ✓ 0m20s (223 files, 159M)
[2026-05-06 19:54:08] Archive DB size: 10G
[2026-05-06 19:54:08] Total time: 9m19s
[2026-05-06 19:54:08] Sync complete for 2026-04-28
[2026-05-06 19:54:08] ========================================
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ pkill -f screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ rm -rf ~/.screenpipe/
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 92 lukas staff 2944 6 May 20:22 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd .npm
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ ll
total 24
drwx------ 9 lukas staff 288 28 Apr 09:18 .
drwx------+ 92 lukas staff 2944 6 May 20:22 ..
drwx------ 5 lukas staff 160 1 Nov 2021 _cacache
drwx------@ 2 lukas staff 64 28 Apr 09:18 _locks
drwx------ 15 lukas staff 480 27 Apr 19:54 _logs
drwxr-xr-x 67 lukas staff 2144 28 Apr 09:17 _npx
-rw-r--r--@ 1 lukas staff 0 26 Apr 19:10 _update-notifier-last-checked
-rw-r--r-- 1 lukas staff 173 28 Apr 09:18 anonymous-cli-metrics.json
-rw-r--r-- 1 lukas staff 4764 31 Jan 2024 eresolve-report.txt
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ rm -rf ~/.npm/_npx
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ ll
total 52920
drwx------+ 92 lukas staff 2944 6 May 20:22 .
drwxr-xr-x 5 root admin 160 23 Aug 2024 ..
-r-------- 1 lukas staff 7 18 Nov 2021 .CFUserTextEncoding
-rw-r--r--@ 1 lukas staff 28676 27 Apr 09:11 .DS_Store
drwx------+ 10 lukas staff 320 28 Apr 17:07 .Trash
drwx------ 5 lukas staff 160 1 Nov 2021 .aws
-rw-r--r-- 1 lukas staff 341470 29 Sep 2022 .babel.json
-rw-------@ 1 lukas staff 388 25 Jul 2025 .bash_history
-rw-r--r--@ 1 lukas staff 115 18 Apr 13:19 .bashrc
drwxr-xr-x 5 lukas staff 160 11 Mar 2023 .bito
drwx------@ 6 lukas staff 192 9 Apr 19:53 .cache
drwxr-xr-x 20 lukas staff 640 27 Apr 08:58 .claude
-rw------- 1 lukas staff 28647 27 Apr 09:12 .claude.json
drwxr-xr-x@ 20 lukas staff 640 12 Mar 09:12 .codeium
drwxrwxrwx@ 3 lukas staff 96 2 Mar 2023 .composer
drwx------ 16 lukas staff 512 21 May 2025 .config
drwxr-xr-x 15 lukas staff 480 23 Dec 2024 .continue
drwx------@ 3 lukas staff 96 16 Feb 19:13 .copilot
drwxr-xr-x@ 5 lukas staff 160 9 Apr 2025 .cursor
drwxr-xr-x@ 5 lukas staff 160 17 Aug 2024 .cursor-tutor
drwxr-xr-x 3 lukas staff 96 8 Sep 2024 .daytona
drwxr-xr-x@ 4 lukas staff 128 18 Feb 10:52 .devdb
drwx------ 24 lukas staff 768 27 Apr 18:14 .docker
drwx------ 15 lukas staff 480 6 Jun 2023 .dropbox
drwxr-xr-x@ 3 lukas staff 96 20 Nov 2022 .fig.dotfiles.bak
-rw-r--r-- 1 lukas staff 138 5 Mar 2022 .gauth
-rw-r--r-- 1 lukas staff 220 25 Nov 2021 .gitconfig
-rw-r--r-- 1 lukas staff 12288 25 Nov 2021 .gitconfig.swp
drwx------ 5 lukas staff 160 18 Nov 2021 .hammerspoon
drwxr-xr-x 3 lukas staff 96 21 Mar 2025 .idlerc
-rw------- 1 lukas staff 20 28 Apr 16:51 .lesshst
drwx------ 5 lukas staff 160 23 Dec 2024 .local
-rw------- 1 lukas staff 204 16 Mar 2024 .netrc
drwx------ 3 lukas staff 96 1 Nov 2021 .node-gyp
-rw------- 1 lukas staff 4 6 Feb 2024 .node_repl_history
-rw-r--r-- 1 lukas staff 17 24 Dec 2023 .notion-enhancer
drwxr-xr-x 4 lukas staff 128 12 Jul 2024 .notion-py
drwx------ 8 lukas staff 256 6 May 20:24 .npm
-rw------- 1 lukas staff 74 20 May 2024 .npmrc
drwx------ 32 lukas staff 1024 25 Jul 2025 .nvm
drwxr-xr-x 4 lukas staff 128 5 Aug 2023 .postman
-rw-r--r--@ 1 lukas staff 77 9 Feb 2023 .profile
-rw-------@ 1 lukas staff 3153 21 Mar 2025 .python_history
drwx------ 2 lukas staff 64 15 Nov 2021 .quicktype-vscode
drwxr-xr-x@ 8 lukas staff 256 16 Feb 08:48 .redis-insight
drwxr-xr-x 4 lukas staff 128 4 Feb 09:35 .sonarlint
drwx------ 15 lukas staff 480 8 Aug 2025 .ssh
drwxr-xr-x@ 3 lukas staff 96 15 Aug 2025 .streamlit
drwx------ 6 lukas staff 192 17 Oct 2022 .swiftpm
-rw------- 1 lukas staff 12143 27 Apr 14:58 .viminfo
drwx------ 5 lukas staff 160 19 Jun 2023 .vscode
drwxr-xr-x@ 3 lukas staff 96 20 Jan 2025 .warp
UW PICO 5.09 New Buffer
[ Read 1 line ]
^G Get Help ^O WriteOut ^R Read File ^Y Prev Pg ^K Cut Text ^C Cur Pos
^X Exit ^J Justify ^W Where is ^V Next Pg ^U UnCut Text ^T To Spell
drwxr-xr-x 4 lukas staff 128 29 Apr 2023 .wdm
drwxr-xr-x@ 5 lukas staff 160 26 Jan 13:03 .windsurf
drwxr-xr-x 4 lukas staff 128 24 Mar 12:03 .yarn
-rw-r--r-- 1 lukas staff 116 30 Mar 10:12 .yarnrc
-rw-r--r-- 1 lukas staff 49518 21 Apr 09:09 .zcompdump
-rw-r--r--@ 1 lukas staff 46758 2 Nov 2025 .zcompdump.Lukas-Kovaliks-MacBook-Pro-Jiminny.23381
-rw-r--r--@ 1 lukas staff 6116 20 Apr 19:52 .zprofile
-rw-r--r-- 1 lukas staff 1468 8 Apr 2022 .zprofile-copy
-rw-r--r--@ 1 lukas staff 2900 15 Mar 2023 .zprofile.pysave
-rw------- 1 lukas staff 1731 29 Jun 2022 .zprofile.save
-rw-r--r-- 1 lukas staff 1569 8 Apr 2022 .zprofilees
-rw------- 1 lukas staff 50310 28 Apr 11:32 .zsh_history
drwx------ 9 lukas staff 288 6 May 2025 .zsh_sessions
-rw-r--r--@ 1 lukas staff 400 18 Apr 13:19 .zshrc
drwx------@ 9 lukas staff 288 20 Apr 20:55 Applications
drwxr-xr-x@ 2 lukas staff 64 22 Oct 2025 CascadeProjects
drwxr-xr-x 4 lukas staff 128 27 Oct 2025 DEV
drwx------@ 10 lukas staff 320 28 Apr 18:52 Desktop
drwx------@ 7 lukas staff 224 26 Mar 14:40 Documents
drwx------@ 44 lukas staff 1408 24 Apr 16:53 Downloads
drwxr-xr-x@ 4 lukas staff 128 17 Mar 20:27 Keychron_Screen
drwx------@ 112 lukas staff 3584 2 Dec 09:19 Library
drwx------ 7 lukas staff 224 12 Feb 2024 Movies
drwx------+ 5 lukas staff 160 25 Sep 2023 Music
drwx------+ 9 lukas staff 288 25 Sep 2023 Pictures
drwx------ 3 lukas staff 96 8 Nov 2021 Postman
drwx------+ 4 lukas staff 128 28 Oct 2021 Public
-rw-r--r--@ 1 lukas staff 3950 15 Dec 09:16 Untitled 4.spf
drwx------ 4 lukas staff 128 2 Jul 2023 Users
-rw-r--r-- 1 lukas staff 17050804 27 Apr 19:18 cleanshot-live.log
-rw-r--r-- 1 lukas staff 9363061 27 Apr 19:24 cleanshot-screenpipe.log
-rw-r--r-- 1 lukas staff 0 12 Apr 12:50 clip.mp4
-rw-r--r-- 1 lukas staff 0 12 Apr 12:51 frame.jpg
drwx------ 3 lukas staff 96 30 Sep 2022 iCloud Drive (Archive)
drwx------ 16 lukas staff 512 3 Nov 2025 jiminny
drwxr-xr-x 3 lukas staff 96 20 Mar 18:47 node_modules
drwxr-xr-x 4 lukas staff 128 21 Oct 2025 raycast
-rw-r--r-- 1 lukas staff 0 1 Mar 14:26 response.bin
-rwxr-xr-x 1 lukas staff 3824 11 Apr 15:16 screenpipe-day.sh
-rw-r--r-- 1 lukas staff 86 20 Mar 18:47 yarn.lock
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
cd: no such file or directory: /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ touch screenpipe_sync.sh
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ nano screenpipe_sync.sh
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ npx screenpipe@latest record --ignored-windows "Boosteroid" --retention-days 7
detected hardware tier: Mid
warning: parakeet is not supported on this platform, using whisper-tiny instead
2026-05-06T20:27:32.721416Z INFO screenpipe_engine::auth_key: api auth: key resolved via auto-generated
checking permissions...
screen recording: ok
microphone: ok
accessibility: ok
2026-05-06T20:27:32.831033Z INFO screenpipe_screen::monitor::macos_version: Detected macOS version: 14.6
2026-05-06T20:27:34.088403Z INFO screenpipe_engine::sleep_monitor: Starting macOS sleep/wake monitor
2026-05-06T20:27:34.089942Z INFO screenpipe_engine::sleep_monitor: Screen lock/unlock observers registered (CFNotificationCenter)
2026-05-06T20:27:34.090417Z INFO screenpipe_engine::sleep_monitor: Display reconfiguration watcher registered (CGDisplayRegisterReconfigurationCallback)
2026-05-06T20:27:34.112650Z INFO screenpipe_engine::permission_monitor: permission monitor started screen=true mic=true accessibility=true keychain=true
2026-05-06T20:27:34.112711Z INFO screenpipe: meeting detector enabled — independent of transcription mode
2026-05-06T20:27:34.619906Z INFO screenpipe: API server listening on [IP_ADDRESS]:3030 (localhost only)
2026-05-06T20:27:34.619937Z INFO screenpipe: API auth enabled — run `screenpipe auth token` to view your key
2026-05-06T20:27:34.619857Z INFO screenpipe_engine::snapshot_compaction: snapshot compaction worker started (min_age=600s, poll=300s)
2026-05-06T20:27:34.619847Z INFO screenpipe_engine::power::manager: power manager started (poll interval: 10s)
2026-05-06T20:27:34.620018Z INFO screenpipe_engine::vision_manager::manager: Starting VisionManager
2026-05-06T20:27:34.624746Z INFO screenpipe_core::pipes: installed built-in pipe: day-recap
2026-05-06T20:27:34.626304Z INFO screenpipe_core::pipes: installed built-in pipe: standup-update
2026-05-06T20:27:34.628597Z INFO screenpipe_core::pipes: installed built-in pipe: ai-habits
2026-05-06T20:27:34.629463Z INFO screenpipe_core::pipes: installed built-in pipe: time-breakdown
2026-05-06T20:27:34.630081Z INFO screenpipe_core::pipes: installed built-in pipe: video-export
2026-05-06T20:27:34.630972Z INFO screenpipe_core::pipes: installed built-in pipe: meeting-summary
2026-05-06T20:27:34.631427Z INFO screenpipe_core::pipes: loaded pipe: day-recap
2026-05-06T20:27:34.631521Z INFO screenpipe_core::pipes: loaded pipe: standup-update
2026-05-06T20:27:34.631587Z INFO screenpipe_core::pipes: loaded pipe: ai-habits
2026-05-06T20:27:34.631640Z INFO screenpipe_core::pipes: loaded pipe: time-breakdown
2026-05-06T20:27:34.631690Z INFO screenpipe_core::pipes: loaded pipe: video-export
2026-05-06T20:27:34.631738Z INFO screenpipe_core::pipes: loaded pipe: meeting-summary
2026-05-06T20:27:34.631752Z INFO screenpipe_core::pipes: loaded 6 pipes from "/Users/lukas/.screenpipe/pipes"
_
__________________ ___ ____ ____ (_____ ___
/ ___/ ___/ ___/ _ \/ _ \/ __ \ / __ \/ / __ \/ _ \
(__ / /__/ / / __/ __/ / / / / /_/ / / /_/ / __/
/____/\___/_/ \___/\___/_/ /_/ / .___/_/ .___/\___/
/_/ /_/
power AI by everything you've seen, said or heard
open source | runs locally | developer friendly
┌────────────────────────┬────────────────────────────────────┐
│ setting │ value │
├────────────────────────┼────────────────────────────────────┤
│ audio chunk duration │ 30 seconds │
│ port │ 3030 │
│ audio disabled │ false │
│ vision disabled │ false │
│ pause on DRM content │ false │
│ audio engine │ Parakeet │
│ vad engine │ Silero │
│ data directory │ /Users/lukas/.screenpipe │
│ debug mode │ false │
│ telemetry │ true │
│ use pii removal │ true │
│ use all monitors │ true │
│ ignored windows │ ["Boosteroid"] │
│ included windows │ [] │
│ cloud sync │ disabled │
│ auto-destruct pid │ 0 │
│ deepgram key │ not set │
│ api auth │ enabled │
│ encrypt secrets │ disabled │
│ retention days │ 7 │
│ retention mode │ media-only (keep transcripts) │
├────────────────────────┼────────────────────────────────────┤
│ languages │ │
│ │ all languages │
├────────────────────────┼────────────────────────────────────┤
│ monitors │ │
│ │ id: 1 │
│ │ id: 2 │
├────────────────────────┼────────────────────────────────────┤
│ audio devices │ │
│ │ MacBook Pro Microphone (input) │
│ │ System Audio (output) │
└────────────────────────┴────────────────────────────────────┘
you are using local processing. all your data stays on your computer.
warning: telemetry is enabled. only error-level data will be sent.
to disable, use the --disable-telemetry flag.
check latest changes here: [URL_WITH_CREDENTIALS] ~ $ 2026-05-06T20:31:45.865813Z INFO screenpipe_audio::device::device_manager: Stopping device: MacBook Pro Microphone (input)
2026-05-06T20:31:45.865820Z INFO screenpipe_audio::device::device_manager: Stopping device: MacBook Pro Microphone (input)
2026-05-06T20:31:45.892593Z INFO screenpipe_audio::audio_manager::manager: audio manager stopped
2026-05-06T20:31:45.892684Z INFO screenpipe: stopping UI event capture
2026-05-06T20:31:45.893002Z INFO screenpipe_engine::meeting_detector: meeting v2: shutdown received, exiting detection loop
2026-05-06T20:31:45.893977Z INFO screenpipe: received shutdown signal for VisionManager
2026-05-06T20:31:45.894556Z INFO screenpipe_engine::vision_manager::manager: Shutting down VisionManager
2026-05-06T20:31:45.894516Z INFO screenpipe_engine::snapshot_compaction: snapshot compaction worker shutting down
2026-05-06T20:31:45.894602Z INFO screenpipe_engine::vision_manager::manager: Stopping VisionManager
2026-05-06T20:31:45.895419Z INFO screenpipe_engine::vision_manager::manager: Stopping vision recording for monitor 2
2026-05-06T20:31:45.895898Z INFO screenpipe_engine::vision_manager::manager: Stopping vision recording for monitor 1
2026-05-06T20:31:45.980559Z INFO screenpipe_engine::ui_recorder: UI recording session ended: 54869993-7b4b-491f-b717-2a583517f9c5
2026-05-06T20:31:45.980777Z INFO screenpipe: shutdown complete
ggml_metal_free: deallocating
2026-05-06T20:31:46.374234Z ERROR screenpipe_engine::event_driven_capture: event capture failed (trigger=click, monitor=1): monitor capture failed: capture task panicked: task 770 was cancelled
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ ;3B
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ sp-start
detected hardware tier: Mid
warning: parakeet is not supported on this platform, using whisper-tiny instead
2026-05-06T20:32:21.850318Z INFO screenpipe_engine::auth_key: api auth: key resolved via secret store
checking permissions...
screen recording: ok
accessibility: ok
2026-05-06T20:32:21.937393Z INFO screenpipe_screen::monitor::macos_version: Detected macOS version: 14.6
2026-05-06T20:32:23.002257Z INFO screenpipe_engine::sleep_monitor: Starting macOS sleep/wake monitor
2026-05-06T20:32:23.006683Z INFO screenpipe_engine::sleep_monitor: Screen lock/unlock observers registered (CFNotificationCenter)
2026-05-06T20:32:23.008348Z INFO screenpipe_engine::sleep_monitor: Display reconfiguration watcher registered (CGDisplayRegisterReconfigurationCallback)
2026-05-06T20:32:23.030912Z INFO screenpipe_engine::permission_monitor: permission monitor started screen=true mic=true accessibility=true keychain=true
2026-05-06T20:32:23.030979Z INFO screenpipe: meeting detector enabled — independent of transcription mode
2026-05-06T20:32:23.031261Z INFO screenpipe: API server listening on [IP_ADDRESS]:3030 (localhost only)
2026-05-06T20:32:23.031328Z INFO screenpipe_engine::vision_manager::manager: Starting VisionManager
2026-05-06T20:32:23.031199Z INFO screenpipe_engine::snapshot_compaction: snapshot compaction worker started (min_age=600s, poll=300s)
2026-05-06T20:32:23.031387Z INFO screenpipe: API auth enabled — run `screenpipe auth token` to view your key
2026-05-06T20:32:23.031253Z INFO screenpipe_engine::power::manager: power manager started (poll interval: 10s)
2026-05-06T20:32:23.034682Z INFO screenpipe_core::pipes: loaded pipe: day-recap
2026-05-06T20:32:23.035042Z INFO screenpipe_core::pipes: loaded pipe: standup-update
2026-05-06T20:32:23.035480Z INFO screenpipe_core::pipes: loaded pipe: ai-habits
2026-05-06T20:32:23.035607Z INFO screenpipe_core::pipes: loaded pipe: time-breakdown
2026-05-06T20:32:23.035705Z INFO screenpipe_core::pipes: loaded pipe: video-export
2026-05-06T20:32:23.035815Z INFO screenpipe_...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
55
|
3
|
14
|
2026-05-06T17:32:47.221644+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778088767221_m1.jpg...
|
iTerm2
|
-zsh
|
True
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $","depth":4,"on_screen":true,"value":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $","is_focused":true},{"role":"AXRadioButton","text":"DOCKER","depth":2,"bounds":{"left":0.0,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.004166667,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"DEV (docker)","depth":2,"bounds":{"left":0.16388889,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.16805555,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"APP (-zsh)","depth":2,"bounds":{"left":0.32777777,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.33194444,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.49166667,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.49583334,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"screenpipe\"","depth":2,"bounds":{"left":0.65555555,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.6597222,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.8194444,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.82361114,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"⌥⌘1","depth":1,"bounds":{"left":0.9548611,"top":0.032222223,"width":0.03888889,"height":0.018888889},"on_screen":true,"automation_id":"_NS:8","role_description":"text"},{"role":"AXStaticText","text":"-zsh","depth":1,"bounds":{"left":0.48819444,"top":0.033333335,"width":0.022916667,"height":0.017777778},"on_screen":true,"role_description":"text"}]...
|
-5583386125247274750
|
8942063973508197633
|
visual_change
|
accessibility
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
53
|
NULL
|
NULL
|
NULL
|
|
56
|
3
|
15
|
2026-05-06T17:34:22.349457+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778088862349_m1.jpg...
|
iTerm2
|
-zsh
|
True
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","depth":4,"on_screen":true,"value":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","is_focused":true},{"role":"AXRadioButton","text":"DOCKER","depth":2,"bounds":{"left":0.0,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.004166667,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"DEV (docker)","depth":2,"bounds":{"left":0.16388889,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.16805555,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"APP (-zsh)","depth":2,"bounds":{"left":0.32777777,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.33194444,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.49166667,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.49583334,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"screenpipe\"","depth":2,"bounds":{"left":0.65555555,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.6597222,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.8194444,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.82361114,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"⌥⌘1","depth":1,"bounds":{"left":0.9548611,"top":0.032222223,"width":0.03888889,"height":0.018888889},"on_screen":true,"automation_id":"_NS:8","role_description":"text"},{"role":"AXStaticText","text":"-zsh","depth":1,"bounds":{"left":0.48819444,"top":0.033333335,"width":0.022916667,"height":0.017777778},"on_screen":true,"role_description":"text"}]...
|
-4581249978965508986
|
3190949638919044609
|
manual
|
accessibility
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
57
|
4
|
15
|
2026-05-06T17:34:22.922290+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778088862922_m2.jpg...
|
iTerm2
|
-zsh
|
True
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","depth":4,"on_screen":true,"value":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","is_focused":true},{"role":"AXRadioButton","text":"DOCKER","depth":2,"bounds":{"left":0.27027926,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.27227393,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"DEV (docker)","depth":2,"bounds":{"left":0.3487367,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.35073137,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"APP (-zsh)","depth":2,"bounds":{"left":0.42719415,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.42918882,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.5056516,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.50764626,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"screenpipe\"","depth":2,"bounds":{"left":0.58410907,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.58610374,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.6625665,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.66456115,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"⌥⌘1","depth":1,"bounds":{"left":0.7273936,"top":1.0,"width":0.01861702,"height":-0.023144484},"on_screen":true,"automation_id":"_NS:8","role_description":"text"},{"role":"AXStaticText","text":"-zsh","depth":1,"bounds":{"left":0.50398934,"top":1.0,"width":0.010970744,"height":-0.02394259},"on_screen":true,"role_description":"text"}]...
|
-4581249978965508986
|
3190949638919044609
|
manual
|
accessibility
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
58
|
NULL
|
0
|
2026-05-06T17:34:55.443888+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778088895443_m1.jpg...
|
iTerm2
|
-zsh
|
True
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","depth":4,"on_screen":true,"value":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","is_focused":true},{"role":"AXRadioButton","text":"DOCKER","depth":2,"bounds":{"left":0.0,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.004166667,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"DEV (docker)","depth":2,"bounds":{"left":0.16388889,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.16805555,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"APP (-zsh)","depth":2,"bounds":{"left":0.32777777,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.33194444,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.49166667,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.49583334,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"screenpipe\"","depth":2,"bounds":{"left":0.65555555,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.6597222,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.8194444,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.82361114,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"⌥⌘1","depth":1,"bounds":{"left":0.9548611,"top":0.032222223,"width":0.03888889,"height":0.018888889},"on_screen":true,"automation_id":"_NS:8","role_description":"text"},{"role":"AXStaticText","text":"-zsh","depth":1,"bounds":{"left":0.48819444,"top":0.033333335,"width":0.022916667,"height":0.017777778},"on_screen":true,"role_description":"text"}]...
|
-4581249978965508986
|
3190949638919044609
|
idle
|
accessibility
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
56
|
NULL
|
NULL
|
NULL
|
|
59
|
NULL
|
0
|
2026-05-06T17:34:57.069521+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778088897069_m2.jpg...
|
iTerm2
|
-zsh
|
True
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","depth":4,"on_screen":true,"value":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","is_focused":true},{"role":"AXRadioButton","text":"DOCKER","depth":2,"bounds":{"left":0.27027926,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.27227393,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"DEV (docker)","depth":2,"bounds":{"left":0.3487367,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.35073137,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"APP (-zsh)","depth":2,"bounds":{"left":0.42719415,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.42918882,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.5056516,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.50764626,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"screenpipe\"","depth":2,"bounds":{"left":0.58410907,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.58610374,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.6625665,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.66456115,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"⌥⌘1","depth":1,"bounds":{"left":0.7273936,"top":1.0,"width":0.01861702,"height":-0.023144484},"on_screen":true,"automation_id":"_NS:8","role_description":"text"},{"role":"AXStaticText","text":"-zsh","depth":1,"bounds":{"left":0.50398934,"top":1.0,"width":0.010970744,"height":-0.02394259},"on_screen":true,"role_description":"text"}]...
|
-4581249978965508986
|
3190949638919044609
|
idle
|
accessibility
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
57
|
NULL
|
NULL
|
NULL
|
|
60
|
5
|
0
|
2026-05-06T17:35:26.328902+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778088926328_m1.jpg...
|
iTerm2
|
-zsh
|
True
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","depth":4,"on_screen":true,"value":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","is_focused":true},{"role":"AXRadioButton","text":"DOCKER","depth":2,"bounds":{"left":0.0,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.004166667,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"DEV (docker)","depth":2,"bounds":{"left":0.16388889,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.16805555,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"APP (-zsh)","depth":2,"bounds":{"left":0.32777777,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.33194444,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.49166667,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.49583334,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"screenpipe\"","depth":2,"bounds":{"left":0.65555555,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.6597222,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.8194444,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.82361114,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"⌥⌘1","depth":1,"bounds":{"left":0.9548611,"top":0.032222223,"width":0.03888889,"height":0.018888889},"on_screen":true,"automation_id":"_NS:8","role_description":"text"},{"role":"AXStaticText","text":"-zsh","depth":1,"bounds":{"left":0.48819444,"top":0.033333335,"width":0.022916667,"height":0.017777778},"on_screen":true,"role_description":"text"}]...
|
-4581249978965508986
|
3190949638919044609
|
idle
|
accessibility
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
56
|
NULL
|
NULL
|
NULL
|
|
61
|
6
|
0
|
2026-05-06T17:35:27.793446+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778088927793_m2.jpg...
|
iTerm2
|
-zsh
|
True
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","depth":4,"on_screen":true,"value":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","is_focused":true},{"role":"AXRadioButton","text":"DOCKER","depth":2,"bounds":{"left":0.27027926,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.27227393,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"DEV (docker)","depth":2,"bounds":{"left":0.3487367,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.35073137,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"APP (-zsh)","depth":2,"bounds":{"left":0.42719415,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.42918882,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.5056516,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.50764626,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"screenpipe\"","depth":2,"bounds":{"left":0.58410907,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.58610374,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.6625665,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.66456115,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"⌥⌘1","depth":1,"bounds":{"left":0.7273936,"top":1.0,"width":0.01861702,"height":-0.023144484},"on_screen":true,"automation_id":"_NS:8","role_description":"text"},{"role":"AXStaticText","text":"-zsh","depth":1,"bounds":{"left":0.50398934,"top":1.0,"width":0.010970744,"height":-0.02394259},"on_screen":true,"role_description":"text"}]...
|
-4581249978965508986
|
3190949638919044609
|
idle
|
accessibility
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
57
|
NULL
|
NULL
|
NULL
|
|
62
|
5
|
1
|
2026-05-06T17:35:57.089817+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778088957089_m1.jpg...
|
iTerm2
|
-zsh
|
True
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","depth":4,"on_screen":true,"value":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","is_focused":true},{"role":"AXRadioButton","text":"DOCKER","depth":2,"bounds":{"left":0.0,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.004166667,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"DEV (docker)","depth":2,"bounds":{"left":0.16388889,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.16805555,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"APP (-zsh)","depth":2,"bounds":{"left":0.32777777,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.33194444,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.49166667,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.49583334,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"screenpipe\"","depth":2,"bounds":{"left":0.65555555,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.6597222,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.8194444,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.82361114,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"⌥⌘1","depth":1,"bounds":{"left":0.9548611,"top":0.032222223,"width":0.03888889,"height":0.018888889},"on_screen":true,"automation_id":"_NS:8","role_description":"text"},{"role":"AXStaticText","text":"-zsh","depth":1,"bounds":{"left":0.48819444,"top":0.033333335,"width":0.022916667,"height":0.017777778},"on_screen":true,"role_description":"text"}]...
|
-4581249978965508986
|
3190949638919044609
|
idle
|
accessibility
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
56
|
NULL
|
NULL
|
NULL
|
|
63
|
6
|
1
|
2026-05-06T17:35:58.635919+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778088958635_m2.jpg...
|
iTerm2
|
-zsh
|
True
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","depth":4,"on_screen":true,"value":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","is_focused":true},{"role":"AXRadioButton","text":"DOCKER","depth":2,"bounds":{"left":0.27027926,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.27227393,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"DEV (docker)","depth":2,"bounds":{"left":0.3487367,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.35073137,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"APP (-zsh)","depth":2,"bounds":{"left":0.42719415,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.42918882,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.5056516,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.50764626,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"screenpipe\"","depth":2,"bounds":{"left":0.58410907,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.58610374,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.6625665,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.66456115,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"⌥⌘1","depth":1,"bounds":{"left":0.7273936,"top":1.0,"width":0.01861702,"height":-0.023144484},"on_screen":true,"automation_id":"_NS:8","role_description":"text"},{"role":"AXStaticText","text":"-zsh","depth":1,"bounds":{"left":0.50398934,"top":1.0,"width":0.010970744,"height":-0.02394259},"on_screen":true,"role_description":"text"}]...
|
-4581249978965508986
|
3190949638919044609
|
idle
|
accessibility
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
57
|
NULL
|
NULL
|
NULL
|
|
64
|
5
|
2
|
2026-05-06T17:36:27.860681+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778088987860_m1.jpg...
|
iTerm2
|
-zsh
|
True
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","depth":4,"on_screen":true,"value":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","is_focused":true},{"role":"AXRadioButton","text":"DOCKER","depth":2,"bounds":{"left":0.0,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.004166667,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"DEV (docker)","depth":2,"bounds":{"left":0.16388889,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.16805555,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"APP (-zsh)","depth":2,"bounds":{"left":0.32777777,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.33194444,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.49166667,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.49583334,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"screenpipe\"","depth":2,"bounds":{"left":0.65555555,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.6597222,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.8194444,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.82361114,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"⌥⌘1","depth":1,"bounds":{"left":0.9548611,"top":0.032222223,"width":0.03888889,"height":0.018888889},"on_screen":true,"automation_id":"_NS:8","role_description":"text"},{"role":"AXStaticText","text":"-zsh","depth":1,"bounds":{"left":0.48819444,"top":0.033333335,"width":0.022916667,"height":0.017777778},"on_screen":true,"role_description":"text"}]...
|
-4581249978965508986
|
3190949638919044609
|
idle
|
accessibility
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
56
|
NULL
|
NULL
|
NULL
|
|
65
|
6
|
2
|
2026-05-06T17:36:29.374818+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778088989374_m2.jpg...
|
iTerm2
|
-zsh
|
True
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","depth":4,"on_screen":true,"value":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","is_focused":true},{"role":"AXRadioButton","text":"DOCKER","depth":2,"bounds":{"left":0.27027926,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.27227393,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"DEV (docker)","depth":2,"bounds":{"left":0.3487367,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.35073137,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"APP (-zsh)","depth":2,"bounds":{"left":0.42719415,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.42918882,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.5056516,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.50764626,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"screenpipe\"","depth":2,"bounds":{"left":0.58410907,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.58610374,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.6625665,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.66456115,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"⌥⌘1","depth":1,"bounds":{"left":0.7273936,"top":1.0,"width":0.01861702,"height":-0.023144484},"on_screen":true,"automation_id":"_NS:8","role_description":"text"},{"role":"AXStaticText","text":"-zsh","depth":1,"bounds":{"left":0.50398934,"top":1.0,"width":0.010970744,"height":-0.02394259},"on_screen":true,"role_description":"text"}]...
|
-4581249978965508986
|
3190949638919044609
|
idle
|
accessibility
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
57
|
NULL
|
NULL
|
NULL
|
|
66
|
5
|
3
|
2026-05-06T17:36:58.527517+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778089018527_m1.jpg...
|
iTerm2
|
-zsh
|
True
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","depth":4,"on_screen":true,"value":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","is_focused":true},{"role":"AXRadioButton","text":"DOCKER","depth":2,"bounds":{"left":0.0,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.004166667,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"DEV (docker)","depth":2,"bounds":{"left":0.16388889,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.16805555,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"APP (-zsh)","depth":2,"bounds":{"left":0.32777777,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.33194444,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.49166667,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.49583334,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"screenpipe\"","depth":2,"bounds":{"left":0.65555555,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.6597222,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.8194444,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.82361114,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"⌥⌘1","depth":1,"bounds":{"left":0.9548611,"top":0.032222223,"width":0.03888889,"height":0.018888889},"on_screen":true,"automation_id":"_NS:8","role_description":"text"},{"role":"AXStaticText","text":"-zsh","depth":1,"bounds":{"left":0.48819444,"top":0.033333335,"width":0.022916667,"height":0.017777778},"on_screen":true,"role_description":"text"}]...
|
-4581249978965508986
|
3190949638919044609
|
idle
|
accessibility
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
56
|
NULL
|
NULL
|
NULL
|
|
67
|
6
|
3
|
2026-05-06T17:37:00.270847+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778089020270_m2.jpg...
|
iTerm2
|
-zsh
|
True
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","depth":4,"on_screen":true,"value":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","is_focused":true},{"role":"AXRadioButton","text":"DOCKER","depth":2,"bounds":{"left":0.27027926,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.27227393,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"DEV (docker)","depth":2,"bounds":{"left":0.3487367,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.35073137,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"APP (-zsh)","depth":2,"bounds":{"left":0.42719415,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.42918882,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.5056516,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.50764626,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"screenpipe\"","depth":2,"bounds":{"left":0.58410907,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.58610374,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.6625665,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.66456115,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"⌥⌘1","depth":1,"bounds":{"left":0.7273936,"top":1.0,"width":0.01861702,"height":-0.023144484},"on_screen":true,"automation_id":"_NS:8","role_description":"text"},{"role":"AXStaticText","text":"-zsh","depth":1,"bounds":{"left":0.50398934,"top":1.0,"width":0.010970744,"height":-0.02394259},"on_screen":true,"role_description":"text"}]...
|
-4581249978965508986
|
3190949638919044609
|
idle
|
accessibility
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
57
|
NULL
|
NULL
|
NULL
|
|
68
|
5
|
4
|
2026-05-06T17:37:29.194727+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778089049194_m1.jpg...
|
iTerm2
|
-zsh
|
True
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","depth":4,"on_screen":true,"value":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","is_focused":true},{"role":"AXRadioButton","text":"DOCKER","depth":2,"bounds":{"left":0.0,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.004166667,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"DEV (docker)","depth":2,"bounds":{"left":0.16388889,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.16805555,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"APP (-zsh)","depth":2,"bounds":{"left":0.32777777,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.33194444,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.49166667,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.49583334,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"screenpipe\"","depth":2,"bounds":{"left":0.65555555,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.6597222,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.8194444,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.82361114,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"⌥⌘1","depth":1,"bounds":{"left":0.9548611,"top":0.032222223,"width":0.03888889,"height":0.018888889},"on_screen":true,"automation_id":"_NS:8","role_description":"text"},{"role":"AXStaticText","text":"-zsh","depth":1,"bounds":{"left":0.48819444,"top":0.033333335,"width":0.022916667,"height":0.017777778},"on_screen":true,"role_description":"text"}]...
|
-4581249978965508986
|
3190949638919044609
|
idle
|
accessibility
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
56
|
NULL
|
NULL
|
NULL
|
|
69
|
6
|
4
|
2026-05-06T17:37:30.974448+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778089050974_m2.jpg...
|
iTerm2
|
-zsh
|
True
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","depth":4,"on_screen":true,"value":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","is_focused":true},{"role":"AXRadioButton","text":"DOCKER","depth":2,"bounds":{"left":0.27027926,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.27227393,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"DEV (docker)","depth":2,"bounds":{"left":0.3487367,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.35073137,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"APP (-zsh)","depth":2,"bounds":{"left":0.42719415,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.42918882,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.5056516,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.50764626,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"screenpipe\"","depth":2,"bounds":{"left":0.58410907,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.58610374,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.6625665,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.66456115,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"⌥⌘1","depth":1,"bounds":{"left":0.7273936,"top":1.0,"width":0.01861702,"height":-0.023144484},"on_screen":true,"automation_id":"_NS:8","role_description":"text"},{"role":"AXStaticText","text":"-zsh","depth":1,"bounds":{"left":0.50398934,"top":1.0,"width":0.010970744,"height":-0.02394259},"on_screen":true,"role_description":"text"}]...
|
-4581249978965508986
|
3190949638919044609
|
idle
|
accessibility
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
57
|
NULL
|
NULL
|
NULL
|
|
70
|
5
|
5
|
2026-05-06T17:37:59.866251+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778089079866_m1.jpg...
|
iTerm2
|
-zsh
|
True
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","depth":4,"on_screen":true,"value":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","is_focused":true},{"role":"AXRadioButton","text":"DOCKER","depth":2,"bounds":{"left":0.0,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.004166667,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"DEV (docker)","depth":2,"bounds":{"left":0.16388889,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.16805555,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"APP (-zsh)","depth":2,"bounds":{"left":0.32777777,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.33194444,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.49166667,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.49583334,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"screenpipe\"","depth":2,"bounds":{"left":0.65555555,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.6597222,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.8194444,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.82361114,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"⌥⌘1","depth":1,"bounds":{"left":0.9548611,"top":0.032222223,"width":0.03888889,"height":0.018888889},"on_screen":true,"automation_id":"_NS:8","role_description":"text"},{"role":"AXStaticText","text":"-zsh","depth":1,"bounds":{"left":0.48819444,"top":0.033333335,"width":0.022916667,"height":0.017777778},"on_screen":true,"role_description":"text"}]...
|
-4581249978965508986
|
3190949638919044609
|
idle
|
accessibility
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
56
|
NULL
|
NULL
|
NULL
|
|
71
|
6
|
5
|
2026-05-06T17:38:01.721296+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778089081721_m2.jpg...
|
iTerm2
|
-zsh
|
True
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","depth":4,"on_screen":true,"value":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","is_focused":true},{"role":"AXRadioButton","text":"DOCKER","depth":2,"bounds":{"left":0.27027926,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.27227393,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"DEV (docker)","depth":2,"bounds":{"left":0.3487367,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.35073137,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"APP (-zsh)","depth":2,"bounds":{"left":0.42719415,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.42918882,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.5056516,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.50764626,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"screenpipe\"","depth":2,"bounds":{"left":0.58410907,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.58610374,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.6625665,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.66456115,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"⌥⌘1","depth":1,"bounds":{"left":0.7273936,"top":1.0,"width":0.01861702,"height":-0.023144484},"on_screen":true,"automation_id":"_NS:8","role_description":"text"},{"role":"AXStaticText","text":"-zsh","depth":1,"bounds":{"left":0.50398934,"top":1.0,"width":0.010970744,"height":-0.02394259},"on_screen":true,"role_description":"text"}]...
|
-4581249978965508986
|
3190949638919044609
|
idle
|
accessibility
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
57
|
NULL
|
NULL
|
NULL
|
|
72
|
5
|
6
|
2026-05-06T17:38:30.848080+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778089110848_m1.jpg...
|
iTerm2
|
-zsh
|
True
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","depth":4,"on_screen":true,"value":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","is_focused":true},{"role":"AXRadioButton","text":"DOCKER","depth":2,"bounds":{"left":0.0,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.004166667,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"DEV (docker)","depth":2,"bounds":{"left":0.16388889,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.16805555,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"APP (-zsh)","depth":2,"bounds":{"left":0.32777777,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.33194444,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.49166667,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.49583334,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"screenpipe\"","depth":2,"bounds":{"left":0.65555555,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.6597222,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.8194444,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.82361114,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"⌥⌘1","depth":1,"bounds":{"left":0.9548611,"top":0.032222223,"width":0.03888889,"height":0.018888889},"on_screen":true,"automation_id":"_NS:8","role_description":"text"},{"role":"AXStaticText","text":"-zsh","depth":1,"bounds":{"left":0.48819444,"top":0.033333335,"width":0.022916667,"height":0.017777778},"on_screen":true,"role_description":"text"}]...
|
-4581249978965508986
|
3190949638919044609
|
idle
|
accessibility
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
56
|
NULL
|
NULL
|
NULL
|
|
73
|
6
|
6
|
2026-05-06T17:38:32.768559+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778089112768_m2.jpg...
|
iTerm2
|
-zsh
|
True
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","depth":4,"on_screen":true,"value":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","is_focused":true},{"role":"AXRadioButton","text":"DOCKER","depth":2,"bounds":{"left":0.27027926,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.27227393,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"DEV (docker)","depth":2,"bounds":{"left":0.3487367,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.35073137,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"APP (-zsh)","depth":2,"bounds":{"left":0.42719415,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.42918882,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.5056516,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.50764626,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"screenpipe\"","depth":2,"bounds":{"left":0.58410907,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.58610374,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.6625665,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.66456115,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"⌥⌘1","depth":1,"bounds":{"left":0.7273936,"top":1.0,"width":0.01861702,"height":-0.023144484},"on_screen":true,"automation_id":"_NS:8","role_description":"text"},{"role":"AXStaticText","text":"-zsh","depth":1,"bounds":{"left":0.50398934,"top":1.0,"width":0.010970744,"height":-0.02394259},"on_screen":true,"role_description":"text"}]...
|
-4581249978965508986
|
3190949638919044609
|
idle
|
accessibility
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
57
|
NULL
|
NULL
|
NULL
|
|
74
|
5
|
7
|
2026-05-06T17:39:01.520984+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778089141520_m1.jpg...
|
iTerm2
|
-zsh
|
True
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","depth":4,"on_screen":true,"value":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","is_focused":true},{"role":"AXRadioButton","text":"DOCKER","depth":2,"bounds":{"left":0.0,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.004166667,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"DEV (docker)","depth":2,"bounds":{"left":0.16388889,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.16805555,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"APP (-zsh)","depth":2,"bounds":{"left":0.32777777,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.33194444,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.49166667,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.49583334,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"screenpipe\"","depth":2,"bounds":{"left":0.65555555,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.6597222,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.8194444,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.82361114,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"⌥⌘1","depth":1,"bounds":{"left":0.9548611,"top":0.032222223,"width":0.03888889,"height":0.018888889},"on_screen":true,"automation_id":"_NS:8","role_description":"text"},{"role":"AXStaticText","text":"-zsh","depth":1,"bounds":{"left":0.48819444,"top":0.033333335,"width":0.022916667,"height":0.017777778},"on_screen":true,"role_description":"text"}]...
|
-4581249978965508986
|
3190949638919044609
|
idle
|
accessibility
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
56
|
NULL
|
NULL
|
NULL
|
|
75
|
6
|
7
|
2026-05-06T17:39:03.498760+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778089143498_m2.jpg...
|
iTerm2
|
-zsh
|
True
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","depth":4,"on_screen":true,"value":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","is_focused":true},{"role":"AXRadioButton","text":"DOCKER","depth":2,"bounds":{"left":0.27027926,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.27227393,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"DEV (docker)","depth":2,"bounds":{"left":0.3487367,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.35073137,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"APP (-zsh)","depth":2,"bounds":{"left":0.42719415,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.42918882,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.5056516,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.50764626,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"screenpipe\"","depth":2,"bounds":{"left":0.58410907,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.58610374,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.6625665,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.66456115,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"⌥⌘1","depth":1,"bounds":{"left":0.7273936,"top":1.0,"width":0.01861702,"height":-0.023144484},"on_screen":true,"automation_id":"_NS:8","role_description":"text"},{"role":"AXStaticText","text":"-zsh","depth":1,"bounds":{"left":0.50398934,"top":1.0,"width":0.010970744,"height":-0.02394259},"on_screen":true,"role_description":"text"}]...
|
-4581249978965508986
|
3190949638919044609
|
idle
|
accessibility
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
57
|
NULL
|
NULL
|
NULL
|
|
76
|
5
|
8
|
2026-05-06T17:39:32.629620+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778089172629_m1.jpg...
|
iTerm2
|
-zsh
|
True
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","depth":4,"on_screen":true,"value":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","is_focused":true},{"role":"AXRadioButton","text":"DOCKER","depth":2,"bounds":{"left":0.0,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.004166667,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"DEV (docker)","depth":2,"bounds":{"left":0.16388889,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.16805555,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"APP (-zsh)","depth":2,"bounds":{"left":0.32777777,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.33194444,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.49166667,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.49583334,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"screenpipe\"","depth":2,"bounds":{"left":0.65555555,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.6597222,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.8194444,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.82361114,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"⌥⌘1","depth":1,"bounds":{"left":0.9548611,"top":0.032222223,"width":0.03888889,"height":0.018888889},"on_screen":true,"automation_id":"_NS:8","role_description":"text"},{"role":"AXStaticText","text":"-zsh","depth":1,"bounds":{"left":0.48819444,"top":0.033333335,"width":0.022916667,"height":0.017777778},"on_screen":true,"role_description":"text"}]...
|
-4581249978965508986
|
3190949638919044609
|
idle
|
accessibility
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
56
|
NULL
|
NULL
|
NULL
|
|
77
|
6
|
8
|
2026-05-06T17:39:34.323807+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778089174323_m2.jpg...
|
iTerm2
|
-zsh
|
True
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","depth":4,"on_screen":true,"value":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","is_focused":true},{"role":"AXRadioButton","text":"DOCKER","depth":2,"bounds":{"left":0.27027926,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.27227393,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"DEV (docker)","depth":2,"bounds":{"left":0.3487367,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.35073137,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"APP (-zsh)","depth":2,"bounds":{"left":0.42719415,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.42918882,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.5056516,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.50764626,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"screenpipe\"","depth":2,"bounds":{"left":0.58410907,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.58610374,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.6625665,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.66456115,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"⌥⌘1","depth":1,"bounds":{"left":0.7273936,"top":1.0,"width":0.01861702,"height":-0.023144484},"on_screen":true,"automation_id":"_NS:8","role_description":"text"},{"role":"AXStaticText","text":"-zsh","depth":1,"bounds":{"left":0.50398934,"top":1.0,"width":0.010970744,"height":-0.02394259},"on_screen":true,"role_description":"text"}]...
|
-4581249978965508986
|
3190949638919044609
|
idle
|
accessibility
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
57
|
NULL
|
NULL
|
NULL
|
|
78
|
NULL
|
0
|
2026-05-06T17:40:03.288414+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778089203288_m1.jpg...
|
iTerm2
|
-zsh
|
True
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","depth":4,"on_screen":true,"value":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","is_focused":true},{"role":"AXRadioButton","text":"DOCKER","depth":2,"bounds":{"left":0.0,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.004166667,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"DEV (docker)","depth":2,"bounds":{"left":0.16388889,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.16805555,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"APP (-zsh)","depth":2,"bounds":{"left":0.32777777,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.33194444,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.49166667,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.49583334,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"screenpipe\"","depth":2,"bounds":{"left":0.65555555,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.6597222,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.8194444,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.82361114,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"⌥⌘1","depth":1,"bounds":{"left":0.9548611,"top":0.032222223,"width":0.03888889,"height":0.018888889},"on_screen":true,"automation_id":"_NS:8","role_description":"text"},{"role":"AXStaticText","text":"-zsh","depth":1,"bounds":{"left":0.48819444,"top":0.033333335,"width":0.022916667,"height":0.017777778},"on_screen":true,"role_description":"text"}]...
|
-4581249978965508986
|
3190949638919044609
|
idle
|
accessibility
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
56
|
NULL
|
NULL
|
NULL
|
|
79
|
NULL
|
0
|
2026-05-06T17:40:05.370003+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778089205370_m2.jpg...
|
iTerm2
|
-zsh
|
True
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","depth":4,"on_screen":true,"value":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","is_focused":true},{"role":"AXRadioButton","text":"DOCKER","depth":2,"bounds":{"left":0.27027926,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.27227393,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"DEV (docker)","depth":2,"bounds":{"left":0.3487367,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.35073137,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"APP (-zsh)","depth":2,"bounds":{"left":0.42719415,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.42918882,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.5056516,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.50764626,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"screenpipe\"","depth":2,"bounds":{"left":0.58410907,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.58610374,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.6625665,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.66456115,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"⌥⌘1","depth":1,"bounds":{"left":0.7273936,"top":1.0,"width":0.01861702,"height":-0.023144484},"on_screen":true,"automation_id":"_NS:8","role_description":"text"},{"role":"AXStaticText","text":"-zsh","depth":1,"bounds":{"left":0.50398934,"top":1.0,"width":0.010970744,"height":-0.02394259},"on_screen":true,"role_description":"text"}]...
|
-4581249978965508986
|
3190949638919044609
|
idle
|
accessibility
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
57
|
NULL
|
NULL
|
NULL
|
|
80
|
7
|
0
|
2026-05-06T17:40:34.520708+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778089234520_m1.jpg...
|
iTerm2
|
-zsh
|
True
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","depth":4,"on_screen":true,"value":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","is_focused":true},{"role":"AXRadioButton","text":"DOCKER","depth":2,"bounds":{"left":0.0,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.004166667,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"DEV (docker)","depth":2,"bounds":{"left":0.16388889,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.16805555,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"APP (-zsh)","depth":2,"bounds":{"left":0.32777777,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.33194444,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.49166667,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.49583334,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"screenpipe\"","depth":2,"bounds":{"left":0.65555555,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.6597222,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.8194444,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.82361114,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"⌥⌘1","depth":1,"bounds":{"left":0.9548611,"top":0.032222223,"width":0.03888889,"height":0.018888889},"on_screen":true,"automation_id":"_NS:8","role_description":"text"},{"role":"AXStaticText","text":"-zsh","depth":1,"bounds":{"left":0.48819444,"top":0.033333335,"width":0.022916667,"height":0.017777778},"on_screen":true,"role_description":"text"}]...
|
-4581249978965508986
|
3190949638919044609
|
idle
|
accessibility
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
56
|
NULL
|
NULL
|
NULL
|
|
81
|
8
|
0
|
2026-05-06T17:40:36.266416+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778089236266_m2.jpg...
|
iTerm2
|
-zsh
|
True
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","depth":4,"on_screen":true,"value":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","is_focused":true},{"role":"AXRadioButton","text":"DOCKER","depth":2,"bounds":{"left":0.27027926,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.27227393,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"DEV (docker)","depth":2,"bounds":{"left":0.3487367,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.35073137,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"APP (-zsh)","depth":2,"bounds":{"left":0.42719415,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.42918882,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.5056516,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.50764626,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"screenpipe\"","depth":2,"bounds":{"left":0.58410907,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.58610374,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.6625665,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.66456115,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"⌥⌘1","depth":1,"bounds":{"left":0.7273936,"top":1.0,"width":0.01861702,"height":-0.023144484},"on_screen":true,"automation_id":"_NS:8","role_description":"text"},{"role":"AXStaticText","text":"-zsh","depth":1,"bounds":{"left":0.50398934,"top":1.0,"width":0.010970744,"height":-0.02394259},"on_screen":true,"role_description":"text"}]...
|
-4581249978965508986
|
3190949638919044609
|
idle
|
accessibility
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
57
|
NULL
|
NULL
|
NULL
|
|
82
|
7
|
1
|
2026-05-06T17:41:05.485689+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778089265485_m1.jpg...
|
iTerm2
|
-zsh
|
True
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","depth":4,"on_screen":true,"value":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","is_focused":true},{"role":"AXRadioButton","text":"DOCKER","depth":2,"bounds":{"left":0.0,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.004166667,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"DEV (docker)","depth":2,"bounds":{"left":0.16388889,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.16805555,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"APP (-zsh)","depth":2,"bounds":{"left":0.32777777,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.33194444,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.49166667,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.49583334,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"screenpipe\"","depth":2,"bounds":{"left":0.65555555,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.6597222,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.8194444,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.82361114,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"⌥⌘1","depth":1,"bounds":{"left":0.9548611,"top":0.032222223,"width":0.03888889,"height":0.018888889},"on_screen":true,"automation_id":"_NS:8","role_description":"text"},{"role":"AXStaticText","text":"-zsh","depth":1,"bounds":{"left":0.48819444,"top":0.033333335,"width":0.022916667,"height":0.017777778},"on_screen":true,"role_description":"text"}]...
|
-4581249978965508986
|
3190949638919044609
|
idle
|
accessibility
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
56
|
NULL
|
NULL
|
NULL
|
|
83
|
8
|
1
|
2026-05-06T17:41:07.383276+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778089267383_m2.jpg...
|
iTerm2
|
-zsh
|
True
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","depth":4,"on_screen":true,"value":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","is_focused":true},{"role":"AXRadioButton","text":"DOCKER","depth":2,"bounds":{"left":0.27027926,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.27227393,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"DEV (docker)","depth":2,"bounds":{"left":0.3487367,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.35073137,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"APP (-zsh)","depth":2,"bounds":{"left":0.42719415,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.42918882,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.5056516,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.50764626,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"screenpipe\"","depth":2,"bounds":{"left":0.58410907,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.58610374,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.6625665,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.66456115,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"⌥⌘1","depth":1,"bounds":{"left":0.7273936,"top":1.0,"width":0.01861702,"height":-0.023144484},"on_screen":true,"automation_id":"_NS:8","role_description":"text"},{"role":"AXStaticText","text":"-zsh","depth":1,"bounds":{"left":0.50398934,"top":1.0,"width":0.010970744,"height":-0.02394259},"on_screen":true,"role_description":"text"}]...
|
-4581249978965508986
|
3190949638919044609
|
idle
|
accessibility
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
57
|
NULL
|
NULL
|
NULL
|
|
84
|
7
|
2
|
2026-05-06T17:41:36.562106+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778089296562_m1.jpg...
|
iTerm2
|
-zsh
|
True
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","depth":4,"on_screen":true,"value":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","is_focused":true},{"role":"AXRadioButton","text":"DOCKER","depth":2,"bounds":{"left":0.0,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.004166667,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"DEV (docker)","depth":2,"bounds":{"left":0.16388889,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.16805555,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"APP (-zsh)","depth":2,"bounds":{"left":0.32777777,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.33194444,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.49166667,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.49583334,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"screenpipe\"","depth":2,"bounds":{"left":0.65555555,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.6597222,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.8194444,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.82361114,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"⌥⌘1","depth":1,"bounds":{"left":0.9548611,"top":0.032222223,"width":0.03888889,"height":0.018888889},"on_screen":true,"automation_id":"_NS:8","role_description":"text"},{"role":"AXStaticText","text":"-zsh","depth":1,"bounds":{"left":0.48819444,"top":0.033333335,"width":0.022916667,"height":0.017777778},"on_screen":true,"role_description":"text"}]...
|
-4581249978965508986
|
3190949638919044609
|
idle
|
accessibility
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
56
|
NULL
|
NULL
|
NULL
|
|
85
|
8
|
2
|
2026-05-06T17:41:38.295561+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778089298295_m2.jpg...
|
iTerm2
|
-zsh
|
True
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","depth":4,"on_screen":true,"value":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","is_focused":true},{"role":"AXRadioButton","text":"DOCKER","depth":2,"bounds":{"left":0.27027926,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.27227393,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"DEV (docker)","depth":2,"bounds":{"left":0.3487367,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.35073137,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"APP (-zsh)","depth":2,"bounds":{"left":0.42719415,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.42918882,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.5056516,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.50764626,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"screenpipe\"","depth":2,"bounds":{"left":0.58410907,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.58610374,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.6625665,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.66456115,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"⌥⌘1","depth":1,"bounds":{"left":0.7273936,"top":1.0,"width":0.01861702,"height":-0.023144484},"on_screen":true,"automation_id":"_NS:8","role_description":"text"},{"role":"AXStaticText","text":"-zsh","depth":1,"bounds":{"left":0.50398934,"top":1.0,"width":0.010970744,"height":-0.02394259},"on_screen":true,"role_description":"text"}]...
|
-4581249978965508986
|
3190949638919044609
|
idle
|
accessibility
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
57
|
NULL
|
NULL
|
NULL
|
|
86
|
7
|
3
|
2026-05-06T17:42:07.270568+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778089327270_m1.jpg...
|
iTerm2
|
-zsh
|
True
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","depth":4,"on_screen":true,"value":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","is_focused":true},{"role":"AXRadioButton","text":"DOCKER","depth":2,"bounds":{"left":0.0,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.004166667,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"DEV (docker)","depth":2,"bounds":{"left":0.16388889,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.16805555,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"APP (-zsh)","depth":2,"bounds":{"left":0.32777777,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.33194444,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.49166667,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.49583334,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"screenpipe\"","depth":2,"bounds":{"left":0.65555555,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.6597222,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.8194444,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.82361114,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"⌥⌘1","depth":1,"bounds":{"left":0.9548611,"top":0.032222223,"width":0.03888889,"height":0.018888889},"on_screen":true,"automation_id":"_NS:8","role_description":"text"},{"role":"AXStaticText","text":"-zsh","depth":1,"bounds":{"left":0.48819444,"top":0.033333335,"width":0.022916667,"height":0.017777778},"on_screen":true,"role_description":"text"}]...
|
-4581249978965508986
|
3190949638919044609
|
idle
|
accessibility
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
56
|
NULL
|
NULL
|
NULL
|
|
87
|
8
|
3
|
2026-05-06T17:42:09.081439+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778089329081_m2.jpg...
|
iTerm2
|
-zsh
|
True
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","depth":4,"on_screen":true,"value":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","is_focused":true},{"role":"AXRadioButton","text":"DOCKER","depth":2,"bounds":{"left":0.27027926,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.27227393,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"DEV (docker)","depth":2,"bounds":{"left":0.3487367,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.35073137,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"APP (-zsh)","depth":2,"bounds":{"left":0.42719415,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.42918882,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.5056516,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.50764626,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"screenpipe\"","depth":2,"bounds":{"left":0.58410907,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.58610374,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.6625665,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.66456115,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"⌥⌘1","depth":1,"bounds":{"left":0.7273936,"top":1.0,"width":0.01861702,"height":-0.023144484},"on_screen":true,"automation_id":"_NS:8","role_description":"text"},{"role":"AXStaticText","text":"-zsh","depth":1,"bounds":{"left":0.50398934,"top":1.0,"width":0.010970744,"height":-0.02394259},"on_screen":true,"role_description":"text"}]...
|
-4581249978965508986
|
3190949638919044609
|
idle
|
accessibility
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
57
|
NULL
|
NULL
|
NULL
|
|
88
|
7
|
4
|
2026-05-06T17:42:38.286953+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778089358286_m1.jpg...
|
iTerm2
|
-zsh
|
True
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 24992
drwxr-xr-x 66 lukas staff 2112 6 May 20:42 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
-rw-r--r-- 1 lukas staff 228402 6 May 20:34 1778088862349_m1.jpg
-rw-r--r-- 1 lukas staff 162494 6 May 20:34 1778088862922_m2.jpg
-rw-r--r-- 1 lukas staff 228391 6 May 20:34 1778088895443_m1.jpg
-rw-r--r-- 1 lukas staff 162695 6 May 20:34 1778088897069_m2.jpg
-rw-r--r-- 1 lukas staff 228420 6 May 20:35 1778088926328_m1.jpg
-rw-r--r-- 1 lukas staff 162684 6 May 20:35 1778088927793_m2.jpg
-rw-r--r-- 1 lukas staff 228407 6 May 20:35 1778088957089_m1.jpg
-rw-r--r-- 1 lukas staff 162545 6 May 20:35 1778088958635_m2.jpg
-rw-r--r-- 1 lukas staff 228407 6 May 20:36 1778088987860_m1.jpg
-rw-r--r-- 1 lukas staff 162483 6 May 20:36 1778088989374_m2.jpg
-rw-r--r-- 1 lukas staff 228420 6 May 20:36 1778089018527_m1.jpg
-rw-r--r-- 1 lukas staff 162536 6 May 20:37 1778089020270_m2.jpg
-rw-r--r-- 1 lukas staff 228372 6 May 20:37 1778089049194_m1.jpg
-rw-r--r-- 1 lukas staff 162683 6 May 20:37 1778089050974_m2.jpg
-rw-r--r-- 1 lukas staff 228412 6 May 20:38 1778089079866_m1.jpg
-rw-r--r-- 1 lukas staff 162494 6 May 20:38 1778089081721_m2.jpg
-rw-r--r-- 1 lukas staff 228380 6 May 20:38 1778089110848_m1.jpg
-rw-r--r-- 1 lukas staff 162606 6 May 20:38 1778089112768_m2.jpg
-rw-r--r-- 1 lukas staff 228380 6 May 20:39 1778089141520_m1.jpg
-rw-r--r-- 1 lukas staff 162611 6 May 20:39 1778089143498_m2.jpg
-rw-r--r-- 1 lukas staff 228353 6 May 20:39 1778089172629_m1.jpg
-rw-r--r-- 1 lukas staff 162480 6 May 20:39 1778089174323_m2.jpg
-rw-r--r-- 1 lukas staff 228332 6 May 20:40 1778089203288_m1.jpg
-rw-r--r-- 1 lukas staff 162502 6 May 20:40 1778089205370_m2.jpg
-rw-r--r-- 1 lukas staff 228372 6 May 20:40 1778089234520_m1.jpg
-rw-r--r-- 1 lukas staff 162571 6 May 20:40 1778089236266_m2.jpg
-rw-r--r-- 1 lukas staff 228416 6 May 20:41 1778089265485_m1.jpg
-rw-r--r-- 1 lukas staff 162636 6 May 20:41 1778089267383_m2.jpg
-rw-r--r-- 1 lukas staff 228362 6 May 20:41 1778089296562_m1.jpg
-rw-r--r-- 1 lukas staff 162564 6 May 20:41 1778089298295_m2.jpg
-rw-r--r-- 1 lukas staff 228392 6 May 20:42 1778089327270_m1.jpg
-rw-r--r-- 1 lukas staff 162605 6 May 20:42 1778089329081_m2.jpg
-rw-r--r-- 1 lukas staff 1038222 6 May 20:40 compact_monitor_1_1778089220643.mp4
-rw-r--r-- 1 lukas staff 327159 6 May 20:40 compact_monitor_2_1778089221749.mp4
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 24992\ndrwxr-xr-x 66 lukas staff 2112 6 May 20:42 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\n-rw-r--r-- 1 lukas staff 228402 6 May 20:34 1778088862349_m1.jpg\n-rw-r--r-- 1 lukas staff 162494 6 May 20:34 1778088862922_m2.jpg\n-rw-r--r-- 1 lukas staff 228391 6 May 20:34 1778088895443_m1.jpg\n-rw-r--r-- 1 lukas staff 162695 6 May 20:34 1778088897069_m2.jpg\n-rw-r--r-- 1 lukas staff 228420 6 May 20:35 1778088926328_m1.jpg\n-rw-r--r-- 1 lukas staff 162684 6 May 20:35 1778088927793_m2.jpg\n-rw-r--r-- 1 lukas staff 228407 6 May 20:35 1778088957089_m1.jpg\n-rw-r--r-- 1 lukas staff 162545 6 May 20:35 1778088958635_m2.jpg\n-rw-r--r-- 1 lukas staff 228407 6 May 20:36 1778088987860_m1.jpg\n-rw-r--r-- 1 lukas staff 162483 6 May 20:36 1778088989374_m2.jpg\n-rw-r--r-- 1 lukas staff 228420 6 May 20:36 1778089018527_m1.jpg\n-rw-r--r-- 1 lukas staff 162536 6 May 20:37 1778089020270_m2.jpg\n-rw-r--r-- 1 lukas staff 228372 6 May 20:37 1778089049194_m1.jpg\n-rw-r--r-- 1 lukas staff 162683 6 May 20:37 1778089050974_m2.jpg\n-rw-r--r-- 1 lukas staff 228412 6 May 20:38 1778089079866_m1.jpg\n-rw-r--r-- 1 lukas staff 162494 6 May 20:38 1778089081721_m2.jpg\n-rw-r--r-- 1 lukas staff 228380 6 May 20:38 1778089110848_m1.jpg\n-rw-r--r-- 1 lukas staff 162606 6 May 20:38 1778089112768_m2.jpg\n-rw-r--r-- 1 lukas staff 228380 6 May 20:39 1778089141520_m1.jpg\n-rw-r--r-- 1 lukas staff 162611 6 May 20:39 1778089143498_m2.jpg\n-rw-r--r-- 1 lukas staff 228353 6 May 20:39 1778089172629_m1.jpg\n-rw-r--r-- 1 lukas staff 162480 6 May 20:39 1778089174323_m2.jpg\n-rw-r--r-- 1 lukas staff 228332 6 May 20:40 1778089203288_m1.jpg\n-rw-r--r-- 1 lukas staff 162502 6 May 20:40 1778089205370_m2.jpg\n-rw-r--r-- 1 lukas staff 228372 6 May 20:40 1778089234520_m1.jpg\n-rw-r--r-- 1 lukas staff 162571 6 May 20:40 1778089236266_m2.jpg\n-rw-r--r-- 1 lukas staff 228416 6 May 20:41 1778089265485_m1.jpg\n-rw-r--r-- 1 lukas staff 162636 6 May 20:41 1778089267383_m2.jpg\n-rw-r--r-- 1 lukas staff 228362 6 May 20:41 1778089296562_m1.jpg\n-rw-r--r-- 1 lukas staff 162564 6 May 20:41 1778089298295_m2.jpg\n-rw-r--r-- 1 lukas staff 228392 6 May 20:42 1778089327270_m1.jpg\n-rw-r--r-- 1 lukas staff 162605 6 May 20:42 1778089329081_m2.jpg\n-rw-r--r-- 1 lukas staff 1038222 6 May 20:40 compact_monitor_1_1778089220643.mp4\n-rw-r--r-- 1 lukas staff 327159 6 May 20:40 compact_monitor_2_1778089221749.mp4\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","depth":4,"on_screen":true,"value":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 24992\ndrwxr-xr-x 66 lukas staff 2112 6 May 20:42 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\n-rw-r--r-- 1 lukas staff 228402 6 May 20:34 1778088862349_m1.jpg\n-rw-r--r-- 1 lukas staff 162494 6 May 20:34 1778088862922_m2.jpg\n-rw-r--r-- 1 lukas staff 228391 6 May 20:34 1778088895443_m1.jpg\n-rw-r--r-- 1 lukas staff 162695 6 May 20:34 1778088897069_m2.jpg\n-rw-r--r-- 1 lukas staff 228420 6 May 20:35 1778088926328_m1.jpg\n-rw-r--r-- 1 lukas staff 162684 6 May 20:35 1778088927793_m2.jpg\n-rw-r--r-- 1 lukas staff 228407 6 May 20:35 1778088957089_m1.jpg\n-rw-r--r-- 1 lukas staff 162545 6 May 20:35 1778088958635_m2.jpg\n-rw-r--r-- 1 lukas staff 228407 6 May 20:36 1778088987860_m1.jpg\n-rw-r--r-- 1 lukas staff 162483 6 May 20:36 1778088989374_m2.jpg\n-rw-r--r-- 1 lukas staff 228420 6 May 20:36 1778089018527_m1.jpg\n-rw-r--r-- 1 lukas staff 162536 6 May 20:37 1778089020270_m2.jpg\n-rw-r--r-- 1 lukas staff 228372 6 May 20:37 1778089049194_m1.jpg\n-rw-r--r-- 1 lukas staff 162683 6 May 20:37 1778089050974_m2.jpg\n-rw-r--r-- 1 lukas staff 228412 6 May 20:38 1778089079866_m1.jpg\n-rw-r--r-- 1 lukas staff 162494 6 May 20:38 1778089081721_m2.jpg\n-rw-r--r-- 1 lukas staff 228380 6 May 20:38 1778089110848_m1.jpg\n-rw-r--r-- 1 lukas staff 162606 6 May 20:38 1778089112768_m2.jpg\n-rw-r--r-- 1 lukas staff 228380 6 May 20:39 1778089141520_m1.jpg\n-rw-r--r-- 1 lukas staff 162611 6 May 20:39 1778089143498_m2.jpg\n-rw-r--r-- 1 lukas staff 228353 6 May 20:39 1778089172629_m1.jpg\n-rw-r--r-- 1 lukas staff 162480 6 May 20:39 1778089174323_m2.jpg\n-rw-r--r-- 1 lukas staff 228332 6 May 20:40 1778089203288_m1.jpg\n-rw-r--r-- 1 lukas staff 162502 6 May 20:40 1778089205370_m2.jpg\n-rw-r--r-- 1 lukas staff 228372 6 May 20:40 1778089234520_m1.jpg\n-rw-r--r-- 1 lukas staff 162571 6 May 20:40 1778089236266_m2.jpg\n-rw-r--r-- 1 lukas staff 228416 6 May 20:41 1778089265485_m1.jpg\n-rw-r--r-- 1 lukas staff 162636 6 May 20:41 1778089267383_m2.jpg\n-rw-r--r-- 1 lukas staff 228362 6 May 20:41 1778089296562_m1.jpg\n-rw-r--r-- 1 lukas staff 162564 6 May 20:41 1778089298295_m2.jpg\n-rw-r--r-- 1 lukas staff 228392 6 May 20:42 1778089327270_m1.jpg\n-rw-r--r-- 1 lukas staff 162605 6 May 20:42 1778089329081_m2.jpg\n-rw-r--r-- 1 lukas staff 1038222 6 May 20:40 compact_monitor_1_1778089220643.mp4\n-rw-r--r-- 1 lukas staff 327159 6 May 20:40 compact_monitor_2_1778089221749.mp4\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","is_focused":true},{"role":"AXRadioButton","text":"DOCKER","depth":2,"bounds":{"left":0.0,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.004166667,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"DEV (docker)","depth":2,"bounds":{"left":0.16388889,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.16805555,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"APP (-zsh)","depth":2,"bounds":{"left":0.32777777,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.33194444,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.49166667,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.49583334,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"screenpipe\"","depth":2,"bounds":{"left":0.65555555,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.6597222,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.8194444,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.82361114,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"⌥⌘1","depth":1,"bounds":{"left":0.9548611,"top":0.032222223,"width":0.03888889,"height":0.018888889},"on_screen":true,"automation_id":"_NS:8","role_description":"text"},{"role":"AXStaticText","text":"-zsh","depth":1,"bounds":{"left":0.48819444,"top":0.033333335,"width":0.022916667,"height":0.017777778},"on_screen":true,"role_description":"text"}]...
|
3982245761352668008
|
2903862479982312961
|
idle
|
accessibility
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 24992
drwxr-xr-x 66 lukas staff 2112 6 May 20:42 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
-rw-r--r-- 1 lukas staff 228402 6 May 20:34 1778088862349_m1.jpg
-rw-r--r-- 1 lukas staff 162494 6 May 20:34 1778088862922_m2.jpg
-rw-r--r-- 1 lukas staff 228391 6 May 20:34 1778088895443_m1.jpg
-rw-r--r-- 1 lukas staff 162695 6 May 20:34 1778088897069_m2.jpg
-rw-r--r-- 1 lukas staff 228420 6 May 20:35 1778088926328_m1.jpg
-rw-r--r-- 1 lukas staff 162684 6 May 20:35 1778088927793_m2.jpg
-rw-r--r-- 1 lukas staff 228407 6 May 20:35 1778088957089_m1.jpg
-rw-r--r-- 1 lukas staff 162545 6 May 20:35 1778088958635_m2.jpg
-rw-r--r-- 1 lukas staff 228407 6 May 20:36 1778088987860_m1.jpg
-rw-r--r-- 1 lukas staff 162483 6 May 20:36 1778088989374_m2.jpg
-rw-r--r-- 1 lukas staff 228420 6 May 20:36 1778089018527_m1.jpg
-rw-r--r-- 1 lukas staff 162536 6 May 20:37 1778089020270_m2.jpg
-rw-r--r-- 1 lukas staff 228372 6 May 20:37 1778089049194_m1.jpg
-rw-r--r-- 1 lukas staff 162683 6 May 20:37 1778089050974_m2.jpg
-rw-r--r-- 1 lukas staff 228412 6 May 20:38 1778089079866_m1.jpg
-rw-r--r-- 1 lukas staff 162494 6 May 20:38 1778089081721_m2.jpg
-rw-r--r-- 1 lukas staff 228380 6 May 20:38 1778089110848_m1.jpg
-rw-r--r-- 1 lukas staff 162606 6 May 20:38 1778089112768_m2.jpg
-rw-r--r-- 1 lukas staff 228380 6 May 20:39 1778089141520_m1.jpg
-rw-r--r-- 1 lukas staff 162611 6 May 20:39 1778089143498_m2.jpg
-rw-r--r-- 1 lukas staff 228353 6 May 20:39 1778089172629_m1.jpg
-rw-r--r-- 1 lukas staff 162480 6 May 20:39 1778089174323_m2.jpg
-rw-r--r-- 1 lukas staff 228332 6 May 20:40 1778089203288_m1.jpg
-rw-r--r-- 1 lukas staff 162502 6 May 20:40 1778089205370_m2.jpg
-rw-r--r-- 1 lukas staff 228372 6 May 20:40 1778089234520_m1.jpg
-rw-r--r-- 1 lukas staff 162571 6 May 20:40 1778089236266_m2.jpg
-rw-r--r-- 1 lukas staff 228416 6 May 20:41 1778089265485_m1.jpg
-rw-r--r-- 1 lukas staff 162636 6 May 20:41 1778089267383_m2.jpg
-rw-r--r-- 1 lukas staff 228362 6 May 20:41 1778089296562_m1.jpg
-rw-r--r-- 1 lukas staff 162564 6 May 20:41 1778089298295_m2.jpg
-rw-r--r-- 1 lukas staff 228392 6 May 20:42 1778089327270_m1.jpg
-rw-r--r-- 1 lukas staff 162605 6 May 20:42 1778089329081_m2.jpg
-rw-r--r-- 1 lukas staff 1038222 6 May 20:40 compact_monitor_1_1778089220643.mp4
-rw-r--r-- 1 lukas staff 327159 6 May 20:40 compact_monitor_2_1778089221749.mp4
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
56
|
NULL
|
NULL
|
NULL
|
|
89
|
8
|
4
|
2026-05-06T17:42:40.293804+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778089360293_m2.jpg...
|
iTerm2
|
-zsh
|
True
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 24992
drwxr-xr-x 66 lukas staff 2112 6 May 20:42 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
-rw-r--r-- 1 lukas staff 228402 6 May 20:34 1778088862349_m1.jpg
-rw-r--r-- 1 lukas staff 162494 6 May 20:34 1778088862922_m2.jpg
-rw-r--r-- 1 lukas staff 228391 6 May 20:34 1778088895443_m1.jpg
-rw-r--r-- 1 lukas staff 162695 6 May 20:34 1778088897069_m2.jpg
-rw-r--r-- 1 lukas staff 228420 6 May 20:35 1778088926328_m1.jpg
-rw-r--r-- 1 lukas staff 162684 6 May 20:35 1778088927793_m2.jpg
-rw-r--r-- 1 lukas staff 228407 6 May 20:35 1778088957089_m1.jpg
-rw-r--r-- 1 lukas staff 162545 6 May 20:35 1778088958635_m2.jpg
-rw-r--r-- 1 lukas staff 228407 6 May 20:36 1778088987860_m1.jpg
-rw-r--r-- 1 lukas staff 162483 6 May 20:36 1778088989374_m2.jpg
-rw-r--r-- 1 lukas staff 228420 6 May 20:36 1778089018527_m1.jpg
-rw-r--r-- 1 lukas staff 162536 6 May 20:37 1778089020270_m2.jpg
-rw-r--r-- 1 lukas staff 228372 6 May 20:37 1778089049194_m1.jpg
-rw-r--r-- 1 lukas staff 162683 6 May 20:37 1778089050974_m2.jpg
-rw-r--r-- 1 lukas staff 228412 6 May 20:38 1778089079866_m1.jpg
-rw-r--r-- 1 lukas staff 162494 6 May 20:38 1778089081721_m2.jpg
-rw-r--r-- 1 lukas staff 228380 6 May 20:38 1778089110848_m1.jpg
-rw-r--r-- 1 lukas staff 162606 6 May 20:38 1778089112768_m2.jpg
-rw-r--r-- 1 lukas staff 228380 6 May 20:39 1778089141520_m1.jpg
-rw-r--r-- 1 lukas staff 162611 6 May 20:39 1778089143498_m2.jpg
-rw-r--r-- 1 lukas staff 228353 6 May 20:39 1778089172629_m1.jpg
-rw-r--r-- 1 lukas staff 162480 6 May 20:39 1778089174323_m2.jpg
-rw-r--r-- 1 lukas staff 228332 6 May 20:40 1778089203288_m1.jpg
-rw-r--r-- 1 lukas staff 162502 6 May 20:40 1778089205370_m2.jpg
-rw-r--r-- 1 lukas staff 228372 6 May 20:40 1778089234520_m1.jpg
-rw-r--r-- 1 lukas staff 162571 6 May 20:40 1778089236266_m2.jpg
-rw-r--r-- 1 lukas staff 228416 6 May 20:41 1778089265485_m1.jpg
-rw-r--r-- 1 lukas staff 162636 6 May 20:41 1778089267383_m2.jpg
-rw-r--r-- 1 lukas staff 228362 6 May 20:41 1778089296562_m1.jpg
-rw-r--r-- 1 lukas staff 162564 6 May 20:41 1778089298295_m2.jpg
-rw-r--r-- 1 lukas staff 228392 6 May 20:42 1778089327270_m1.jpg
-rw-r--r-- 1 lukas staff 162605 6 May 20:42 1778089329081_m2.jpg
-rw-r--r-- 1 lukas staff 1038222 6 May 20:40 compact_monitor_1_1778089220643.mp4
-rw-r--r-- 1 lukas staff 327159 6 May 20:40 compact_monitor_2_1778089221749.mp4
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 24992\ndrwxr-xr-x 66 lukas staff 2112 6 May 20:42 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\n-rw-r--r-- 1 lukas staff 228402 6 May 20:34 1778088862349_m1.jpg\n-rw-r--r-- 1 lukas staff 162494 6 May 20:34 1778088862922_m2.jpg\n-rw-r--r-- 1 lukas staff 228391 6 May 20:34 1778088895443_m1.jpg\n-rw-r--r-- 1 lukas staff 162695 6 May 20:34 1778088897069_m2.jpg\n-rw-r--r-- 1 lukas staff 228420 6 May 20:35 1778088926328_m1.jpg\n-rw-r--r-- 1 lukas staff 162684 6 May 20:35 1778088927793_m2.jpg\n-rw-r--r-- 1 lukas staff 228407 6 May 20:35 1778088957089_m1.jpg\n-rw-r--r-- 1 lukas staff 162545 6 May 20:35 1778088958635_m2.jpg\n-rw-r--r-- 1 lukas staff 228407 6 May 20:36 1778088987860_m1.jpg\n-rw-r--r-- 1 lukas staff 162483 6 May 20:36 1778088989374_m2.jpg\n-rw-r--r-- 1 lukas staff 228420 6 May 20:36 1778089018527_m1.jpg\n-rw-r--r-- 1 lukas staff 162536 6 May 20:37 1778089020270_m2.jpg\n-rw-r--r-- 1 lukas staff 228372 6 May 20:37 1778089049194_m1.jpg\n-rw-r--r-- 1 lukas staff 162683 6 May 20:37 1778089050974_m2.jpg\n-rw-r--r-- 1 lukas staff 228412 6 May 20:38 1778089079866_m1.jpg\n-rw-r--r-- 1 lukas staff 162494 6 May 20:38 1778089081721_m2.jpg\n-rw-r--r-- 1 lukas staff 228380 6 May 20:38 1778089110848_m1.jpg\n-rw-r--r-- 1 lukas staff 162606 6 May 20:38 1778089112768_m2.jpg\n-rw-r--r-- 1 lukas staff 228380 6 May 20:39 1778089141520_m1.jpg\n-rw-r--r-- 1 lukas staff 162611 6 May 20:39 1778089143498_m2.jpg\n-rw-r--r-- 1 lukas staff 228353 6 May 20:39 1778089172629_m1.jpg\n-rw-r--r-- 1 lukas staff 162480 6 May 20:39 1778089174323_m2.jpg\n-rw-r--r-- 1 lukas staff 228332 6 May 20:40 1778089203288_m1.jpg\n-rw-r--r-- 1 lukas staff 162502 6 May 20:40 1778089205370_m2.jpg\n-rw-r--r-- 1 lukas staff 228372 6 May 20:40 1778089234520_m1.jpg\n-rw-r--r-- 1 lukas staff 162571 6 May 20:40 1778089236266_m2.jpg\n-rw-r--r-- 1 lukas staff 228416 6 May 20:41 1778089265485_m1.jpg\n-rw-r--r-- 1 lukas staff 162636 6 May 20:41 1778089267383_m2.jpg\n-rw-r--r-- 1 lukas staff 228362 6 May 20:41 1778089296562_m1.jpg\n-rw-r--r-- 1 lukas staff 162564 6 May 20:41 1778089298295_m2.jpg\n-rw-r--r-- 1 lukas staff 228392 6 May 20:42 1778089327270_m1.jpg\n-rw-r--r-- 1 lukas staff 162605 6 May 20:42 1778089329081_m2.jpg\n-rw-r--r-- 1 lukas staff 1038222 6 May 20:40 compact_monitor_1_1778089220643.mp4\n-rw-r--r-- 1 lukas staff 327159 6 May 20:40 compact_monitor_2_1778089221749.mp4\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","depth":4,"on_screen":true,"value":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 24992\ndrwxr-xr-x 66 lukas staff 2112 6 May 20:42 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\n-rw-r--r-- 1 lukas staff 228402 6 May 20:34 1778088862349_m1.jpg\n-rw-r--r-- 1 lukas staff 162494 6 May 20:34 1778088862922_m2.jpg\n-rw-r--r-- 1 lukas staff 228391 6 May 20:34 1778088895443_m1.jpg\n-rw-r--r-- 1 lukas staff 162695 6 May 20:34 1778088897069_m2.jpg\n-rw-r--r-- 1 lukas staff 228420 6 May 20:35 1778088926328_m1.jpg\n-rw-r--r-- 1 lukas staff 162684 6 May 20:35 1778088927793_m2.jpg\n-rw-r--r-- 1 lukas staff 228407 6 May 20:35 1778088957089_m1.jpg\n-rw-r--r-- 1 lukas staff 162545 6 May 20:35 1778088958635_m2.jpg\n-rw-r--r-- 1 lukas staff 228407 6 May 20:36 1778088987860_m1.jpg\n-rw-r--r-- 1 lukas staff 162483 6 May 20:36 1778088989374_m2.jpg\n-rw-r--r-- 1 lukas staff 228420 6 May 20:36 1778089018527_m1.jpg\n-rw-r--r-- 1 lukas staff 162536 6 May 20:37 1778089020270_m2.jpg\n-rw-r--r-- 1 lukas staff 228372 6 May 20:37 1778089049194_m1.jpg\n-rw-r--r-- 1 lukas staff 162683 6 May 20:37 1778089050974_m2.jpg\n-rw-r--r-- 1 lukas staff 228412 6 May 20:38 1778089079866_m1.jpg\n-rw-r--r-- 1 lukas staff 162494 6 May 20:38 1778089081721_m2.jpg\n-rw-r--r-- 1 lukas staff 228380 6 May 20:38 1778089110848_m1.jpg\n-rw-r--r-- 1 lukas staff 162606 6 May 20:38 1778089112768_m2.jpg\n-rw-r--r-- 1 lukas staff 228380 6 May 20:39 1778089141520_m1.jpg\n-rw-r--r-- 1 lukas staff 162611 6 May 20:39 1778089143498_m2.jpg\n-rw-r--r-- 1 lukas staff 228353 6 May 20:39 1778089172629_m1.jpg\n-rw-r--r-- 1 lukas staff 162480 6 May 20:39 1778089174323_m2.jpg\n-rw-r--r-- 1 lukas staff 228332 6 May 20:40 1778089203288_m1.jpg\n-rw-r--r-- 1 lukas staff 162502 6 May 20:40 1778089205370_m2.jpg\n-rw-r--r-- 1 lukas staff 228372 6 May 20:40 1778089234520_m1.jpg\n-rw-r--r-- 1 lukas staff 162571 6 May 20:40 1778089236266_m2.jpg\n-rw-r--r-- 1 lukas staff 228416 6 May 20:41 1778089265485_m1.jpg\n-rw-r--r-- 1 lukas staff 162636 6 May 20:41 1778089267383_m2.jpg\n-rw-r--r-- 1 lukas staff 228362 6 May 20:41 1778089296562_m1.jpg\n-rw-r--r-- 1 lukas staff 162564 6 May 20:41 1778089298295_m2.jpg\n-rw-r--r-- 1 lukas staff 228392 6 May 20:42 1778089327270_m1.jpg\n-rw-r--r-- 1 lukas staff 162605 6 May 20:42 1778089329081_m2.jpg\n-rw-r--r-- 1 lukas staff 1038222 6 May 20:40 compact_monitor_1_1778089220643.mp4\n-rw-r--r-- 1 lukas staff 327159 6 May 20:40 compact_monitor_2_1778089221749.mp4\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","is_focused":true},{"role":"AXRadioButton","text":"DOCKER","depth":2,"bounds":{"left":0.27027926,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.27227393,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"DEV (docker)","depth":2,"bounds":{"left":0.3487367,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.35073137,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"APP (-zsh)","depth":2,"bounds":{"left":0.42719415,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.42918882,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.5056516,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.50764626,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"screenpipe\"","depth":2,"bounds":{"left":0.58410907,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.58610374,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.6625665,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.66456115,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"⌥⌘1","depth":1,"bounds":{"left":0.7273936,"top":1.0,"width":0.01861702,"height":-0.023144484},"on_screen":true,"automation_id":"_NS:8","role_description":"text"},{"role":"AXStaticText","text":"-zsh","depth":1,"bounds":{"left":0.50398934,"top":1.0,"width":0.010970744,"height":-0.02394259},"on_screen":true,"role_description":"text"}]...
|
3982245761352668008
|
2903862479982312961
|
idle
|
accessibility
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 24992
drwxr-xr-x 66 lukas staff 2112 6 May 20:42 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
-rw-r--r-- 1 lukas staff 228402 6 May 20:34 1778088862349_m1.jpg
-rw-r--r-- 1 lukas staff 162494 6 May 20:34 1778088862922_m2.jpg
-rw-r--r-- 1 lukas staff 228391 6 May 20:34 1778088895443_m1.jpg
-rw-r--r-- 1 lukas staff 162695 6 May 20:34 1778088897069_m2.jpg
-rw-r--r-- 1 lukas staff 228420 6 May 20:35 1778088926328_m1.jpg
-rw-r--r-- 1 lukas staff 162684 6 May 20:35 1778088927793_m2.jpg
-rw-r--r-- 1 lukas staff 228407 6 May 20:35 1778088957089_m1.jpg
-rw-r--r-- 1 lukas staff 162545 6 May 20:35 1778088958635_m2.jpg
-rw-r--r-- 1 lukas staff 228407 6 May 20:36 1778088987860_m1.jpg
-rw-r--r-- 1 lukas staff 162483 6 May 20:36 1778088989374_m2.jpg
-rw-r--r-- 1 lukas staff 228420 6 May 20:36 1778089018527_m1.jpg
-rw-r--r-- 1 lukas staff 162536 6 May 20:37 1778089020270_m2.jpg
-rw-r--r-- 1 lukas staff 228372 6 May 20:37 1778089049194_m1.jpg
-rw-r--r-- 1 lukas staff 162683 6 May 20:37 1778089050974_m2.jpg
-rw-r--r-- 1 lukas staff 228412 6 May 20:38 1778089079866_m1.jpg
-rw-r--r-- 1 lukas staff 162494 6 May 20:38 1778089081721_m2.jpg
-rw-r--r-- 1 lukas staff 228380 6 May 20:38 1778089110848_m1.jpg
-rw-r--r-- 1 lukas staff 162606 6 May 20:38 1778089112768_m2.jpg
-rw-r--r-- 1 lukas staff 228380 6 May 20:39 1778089141520_m1.jpg
-rw-r--r-- 1 lukas staff 162611 6 May 20:39 1778089143498_m2.jpg
-rw-r--r-- 1 lukas staff 228353 6 May 20:39 1778089172629_m1.jpg
-rw-r--r-- 1 lukas staff 162480 6 May 20:39 1778089174323_m2.jpg
-rw-r--r-- 1 lukas staff 228332 6 May 20:40 1778089203288_m1.jpg
-rw-r--r-- 1 lukas staff 162502 6 May 20:40 1778089205370_m2.jpg
-rw-r--r-- 1 lukas staff 228372 6 May 20:40 1778089234520_m1.jpg
-rw-r--r-- 1 lukas staff 162571 6 May 20:40 1778089236266_m2.jpg
-rw-r--r-- 1 lukas staff 228416 6 May 20:41 1778089265485_m1.jpg
-rw-r--r-- 1 lukas staff 162636 6 May 20:41 1778089267383_m2.jpg
-rw-r--r-- 1 lukas staff 228362 6 May 20:41 1778089296562_m1.jpg
-rw-r--r-- 1 lukas staff 162564 6 May 20:41 1778089298295_m2.jpg
-rw-r--r-- 1 lukas staff 228392 6 May 20:42 1778089327270_m1.jpg
-rw-r--r-- 1 lukas staff 162605 6 May 20:42 1778089329081_m2.jpg
-rw-r--r-- 1 lukas staff 1038222 6 May 20:40 compact_monitor_1_1778089220643.mp4
-rw-r--r-- 1 lukas staff 327159 6 May 20:40 compact_monitor_2_1778089221749.mp4
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
57
|
NULL
|
NULL
|
NULL
|
|
90
|
7
|
5
|
2026-05-06T17:43:09.059709+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778089389059_m1.jpg...
|
iTerm2
|
-zsh
|
True
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 24992
drwxr-xr-x 66 lukas staff 2112 6 May 20:42 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
-rw-r--r-- 1 lukas staff 228402 6 May 20:34 1778088862349_m1.jpg
-rw-r--r-- 1 lukas staff 162494 6 May 20:34 1778088862922_m2.jpg
-rw-r--r-- 1 lukas staff 228391 6 May 20:34 1778088895443_m1.jpg
-rw-r--r-- 1 lukas staff 162695 6 May 20:34 1778088897069_m2.jpg
-rw-r--r-- 1 lukas staff 228420 6 May 20:35 1778088926328_m1.jpg
-rw-r--r-- 1 lukas staff 162684 6 May 20:35 1778088927793_m2.jpg
-rw-r--r-- 1 lukas staff 228407 6 May 20:35 1778088957089_m1.jpg
-rw-r--r-- 1 lukas staff 162545 6 May 20:35 1778088958635_m2.jpg
-rw-r--r-- 1 lukas staff 228407 6 May 20:36 1778088987860_m1.jpg
-rw-r--r-- 1 lukas staff 162483 6 May 20:36 1778088989374_m2.jpg
-rw-r--r-- 1 lukas staff 228420 6 May 20:36 1778089018527_m1.jpg
-rw-r--r-- 1 lukas staff 162536 6 May 20:37 1778089020270_m2.jpg
-rw-r--r-- 1 lukas staff 228372 6 May 20:37 1778089049194_m1.jpg
-rw-r--r-- 1 lukas staff 162683 6 May 20:37 1778089050974_m2.jpg
-rw-r--r-- 1 lukas staff 228412 6 May 20:38 1778089079866_m1.jpg
-rw-r--r-- 1 lukas staff 162494 6 May 20:38 1778089081721_m2.jpg
-rw-r--r-- 1 lukas staff 228380 6 May 20:38 1778089110848_m1.jpg
-rw-r--r-- 1 lukas staff 162606 6 May 20:38 1778089112768_m2.jpg
-rw-r--r-- 1 lukas staff 228380 6 May 20:39 1778089141520_m1.jpg
-rw-r--r-- 1 lukas staff 162611 6 May 20:39 1778089143498_m2.jpg
-rw-r--r-- 1 lukas staff 228353 6 May 20:39 1778089172629_m1.jpg
-rw-r--r-- 1 lukas staff 162480 6 May 20:39 1778089174323_m2.jpg
-rw-r--r-- 1 lukas staff 228332 6 May 20:40 1778089203288_m1.jpg
-rw-r--r-- 1 lukas staff 162502 6 May 20:40 1778089205370_m2.jpg
-rw-r--r-- 1 lukas staff 228372 6 May 20:40 1778089234520_m1.jpg
-rw-r--r-- 1 lukas staff 162571 6 May 20:40 1778089236266_m2.jpg
-rw-r--r-- 1 lukas staff 228416 6 May 20:41 1778089265485_m1.jpg
-rw-r--r-- 1 lukas staff 162636 6 May 20:41 1778089267383_m2.jpg
-rw-r--r-- 1 lukas staff 228362 6 May 20:41 1778089296562_m1.jpg
-rw-r--r-- 1 lukas staff 162564 6 May 20:41 1778089298295_m2.jpg
-rw-r--r-- 1 lukas staff 228392 6 May 20:42 1778089327270_m1.jpg
-rw-r--r-- 1 lukas staff 162605 6 May 20:42 1778089329081_m2.jpg
-rw-r--r-- 1 lukas staff 1038222 6 May 20:40 compact_monitor_1_1778089220643.mp4
-rw-r--r-- 1 lukas staff 327159 6 May 20:40 compact_monitor_2_1778089221749.mp4
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 25768
drwxr-xr-x 68 lukas staff 2176 6 May 20:42 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
-rw-r--r-- 1 lukas staff 228402 6 May 20:34 1778088862349_m1.jpg
-rw-r--r-- 1 lukas staff 162494 6 May 20:34 1778088862922_m2.jpg
-rw-r--r-- 1 lukas staff 228391 6 May 20:34 1778088895443_m1.jpg
-rw-r--r-- 1 lukas staff 162695 6 May 20:34 1778088897069_m2.jpg
-rw-r--r-- 1 lukas staff 228420 6 May 20:35 1778088926328_m1.jpg
-rw-r--r-- 1 lukas staff 162684 6 May 20:35 1778088927793_m2.jpg
-rw-r--r-- 1 lukas staff 228407 6 May 20:35 1778088957089_m1.jpg
-rw-r--r-- 1 lukas staff 162545 6 May 20:35 1778088958635_m2.jpg
-rw-r--r-- 1 lukas staff 228407 6 May 20:36 1778088987860_m1.jpg
-rw-r--r-- 1 lukas staff 162483 6 May 20:36 1778088989374_m2.jpg
-rw-r--r-- 1 lukas staff 228420 6 May 20:36 1778089018527_m1.jpg
-rw-r--r-- 1 lukas staff 162536 6 May 20:37 1778089020270_m2.jpg
-rw-r--r-- 1 lukas staff 228372 6 May 20:37 1778089049194_m1.jpg
-rw-r--r-- 1 lukas staff 162683 6 May 20:37 1778089050974_m2.jpg
-rw-r--r-- 1 lukas staff 228412 6 May 20:38 1778089079866_m1.jpg
-rw-r--r-- 1 lukas staff 162494 6 May 20:38 1778089081721_m2.jpg
-rw-r--r-- 1 lukas staff 228380 6 May 20:38 1778089110848_m1.jpg
-rw-r--r-- 1 lukas staff 162606 6 May 20:38 1778089112768_m2.jpg
-rw-r--r-- 1 lukas staff 228380 6 May 20:39 1778089141520_m1.jpg
-rw-r--r-- 1 lukas staff 162611 6 May 20:39 1778089143498_m2.jpg
-rw-r--r-- 1 lukas staff 228353 6 May 20:39 1778089172629_m1.jpg
-rw-r--r-- 1 lukas staff 162480 6 May 20:39 1778089174323_m2.jpg
-rw-r--r-- 1 lukas staff 228332 6 May 20:40 1778089203288_m1.jpg
-rw-r--r-- 1 lukas staff 162502 6 May 20:40 1778089205370_m2.jpg
-rw-r--r-- 1 lukas staff 228372 6 May 20:40 1778089234520_m1.jpg
-rw-r--r-- 1 lukas staff 162571 6 May 20:40 1778089236266_m2.jpg
-rw-r--r-- 1 lukas staff 228416 6 May 20:41 1778089265485_m1.jpg
-rw-r--r-- 1 lukas staff 162636 6 May 20:41 1778089267383_m2.jpg
-rw-r--r-- 1 lukas staff 228362 6 May 20:41 1778089296562_m1.jpg
-rw-r--r-- 1 lukas staff 162564 6 May 20:41 1778089298295_m2.jpg
-rw-r--r-- 1 lukas staff 228392 6 May 20:42 1778089327270_m1.jpg
-rw-r--r-- 1 lukas staff 162605 6 May 20:42 1778089329081_m2.jpg
-rw-r--r-- 1 lukas staff 230328 6 May 20:42 1778089358286_m1.jpg
-rw-r--r-- 1 lukas staff 162589 6 May 20:42 1778089360293_m2.jpg
-rw-r--r-- 1 lukas staff 1038222 6 May 20:40 compact_monitor_1_1778089220643.mp4
-rw-r--r-- 1 lukas staff 327159 6 May 20:40 compact_monitor_2_1778089221749.mp4
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 24992\ndrwxr-xr-x 66 lukas staff 2112 6 May 20:42 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\n-rw-r--r-- 1 lukas staff 228402 6 May 20:34 1778088862349_m1.jpg\n-rw-r--r-- 1 lukas staff 162494 6 May 20:34 1778088862922_m2.jpg\n-rw-r--r-- 1 lukas staff 228391 6 May 20:34 1778088895443_m1.jpg\n-rw-r--r-- 1 lukas staff 162695 6 May 20:34 1778088897069_m2.jpg\n-rw-r--r-- 1 lukas staff 228420 6 May 20:35 1778088926328_m1.jpg\n-rw-r--r-- 1 lukas staff 162684 6 May 20:35 1778088927793_m2.jpg\n-rw-r--r-- 1 lukas staff 228407 6 May 20:35 1778088957089_m1.jpg\n-rw-r--r-- 1 lukas staff 162545 6 May 20:35 1778088958635_m2.jpg\n-rw-r--r-- 1 lukas staff 228407 6 May 20:36 1778088987860_m1.jpg\n-rw-r--r-- 1 lukas staff 162483 6 May 20:36 1778088989374_m2.jpg\n-rw-r--r-- 1 lukas staff 228420 6 May 20:36 1778089018527_m1.jpg\n-rw-r--r-- 1 lukas staff 162536 6 May 20:37 1778089020270_m2.jpg\n-rw-r--r-- 1 lukas staff 228372 6 May 20:37 1778089049194_m1.jpg\n-rw-r--r-- 1 lukas staff 162683 6 May 20:37 1778089050974_m2.jpg\n-rw-r--r-- 1 lukas staff 228412 6 May 20:38 1778089079866_m1.jpg\n-rw-r--r-- 1 lukas staff 162494 6 May 20:38 1778089081721_m2.jpg\n-rw-r--r-- 1 lukas staff 228380 6 May 20:38 1778089110848_m1.jpg\n-rw-r--r-- 1 lukas staff 162606 6 May 20:38 1778089112768_m2.jpg\n-rw-r--r-- 1 lukas staff 228380 6 May 20:39 1778089141520_m1.jpg\n-rw-r--r-- 1 lukas staff 162611 6 May 20:39 1778089143498_m2.jpg\n-rw-r--r-- 1 lukas staff 228353 6 May 20:39 1778089172629_m1.jpg\n-rw-r--r-- 1 lukas staff 162480 6 May 20:39 1778089174323_m2.jpg\n-rw-r--r-- 1 lukas staff 228332 6 May 20:40 1778089203288_m1.jpg\n-rw-r--r-- 1 lukas staff 162502 6 May 20:40 1778089205370_m2.jpg\n-rw-r--r-- 1 lukas staff 228372 6 May 20:40 1778089234520_m1.jpg\n-rw-r--r-- 1 lukas staff 162571 6 May 20:40 1778089236266_m2.jpg\n-rw-r--r-- 1 lukas staff 228416 6 May 20:41 1778089265485_m1.jpg\n-rw-r--r-- 1 lukas staff 162636 6 May 20:41 1778089267383_m2.jpg\n-rw-r--r-- 1 lukas staff 228362 6 May 20:41 1778089296562_m1.jpg\n-rw-r--r-- 1 lukas staff 162564 6 May 20:41 1778089298295_m2.jpg\n-rw-r--r-- 1 lukas staff 228392 6 May 20:42 1778089327270_m1.jpg\n-rw-r--r-- 1 lukas staff 162605 6 May 20:42 1778089329081_m2.jpg\n-rw-r--r-- 1 lukas staff 1038222 6 May 20:40 compact_monitor_1_1778089220643.mp4\n-rw-r--r-- 1 lukas staff 327159 6 May 20:40 compact_monitor_2_1778089221749.mp4\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 25768\ndrwxr-xr-x 68 lukas staff 2176 6 May 20:42 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\n-rw-r--r-- 1 lukas staff 228402 6 May 20:34 1778088862349_m1.jpg\n-rw-r--r-- 1 lukas staff 162494 6 May 20:34 1778088862922_m2.jpg\n-rw-r--r-- 1 lukas staff 228391 6 May 20:34 1778088895443_m1.jpg\n-rw-r--r-- 1 lukas staff 162695 6 May 20:34 1778088897069_m2.jpg\n-rw-r--r-- 1 lukas staff 228420 6 May 20:35 1778088926328_m1.jpg\n-rw-r--r-- 1 lukas staff 162684 6 May 20:35 1778088927793_m2.jpg\n-rw-r--r-- 1 lukas staff 228407 6 May 20:35 1778088957089_m1.jpg\n-rw-r--r-- 1 lukas staff 162545 6 May 20:35 1778088958635_m2.jpg\n-rw-r--r-- 1 lukas staff 228407 6 May 20:36 1778088987860_m1.jpg\n-rw-r--r-- 1 lukas staff 162483 6 May 20:36 1778088989374_m2.jpg\n-rw-r--r-- 1 lukas staff 228420 6 May 20:36 1778089018527_m1.jpg\n-rw-r--r-- 1 lukas staff 162536 6 May 20:37 1778089020270_m2.jpg\n-rw-r--r-- 1 lukas staff 228372 6 May 20:37 1778089049194_m1.jpg\n-rw-r--r-- 1 lukas staff 162683 6 May 20:37 1778089050974_m2.jpg\n-rw-r--r-- 1 lukas staff 228412 6 May 20:38 1778089079866_m1.jpg\n-rw-r--r-- 1 lukas staff 162494 6 May 20:38 1778089081721_m2.jpg\n-rw-r--r-- 1 lukas staff 228380 6 May 20:38 1778089110848_m1.jpg\n-rw-r--r-- 1 lukas staff 162606 6 May 20:38 1778089112768_m2.jpg\n-rw-r--r-- 1 lukas staff 228380 6 May 20:39 1778089141520_m1.jpg\n-rw-r--r-- 1 lukas staff 162611 6 May 20:39 1778089143498_m2.jpg\n-rw-r--r-- 1 lukas staff 228353 6 May 20:39 1778089172629_m1.jpg\n-rw-r--r-- 1 lukas staff 162480 6 May 20:39 1778089174323_m2.jpg\n-rw-r--r-- 1 lukas staff 228332 6 May 20:40 1778089203288_m1.jpg\n-rw-r--r-- 1 lukas staff 162502 6 May 20:40 1778089205370_m2.jpg\n-rw-r--r-- 1 lukas staff 228372 6 May 20:40 1778089234520_m1.jpg\n-rw-r--r-- 1 lukas staff 162571 6 May 20:40 1778089236266_m2.jpg\n-rw-r--r-- 1 lukas staff 228416 6 May 20:41 1778089265485_m1.jpg\n-rw-r--r-- 1 lukas staff 162636 6 May 20:41 1778089267383_m2.jpg\n-rw-r--r-- 1 lukas staff 228362 6 May 20:41 1778089296562_m1.jpg\n-rw-r--r-- 1 lukas staff 162564 6 May 20:41 1778089298295_m2.jpg\n-rw-r--r-- 1 lukas staff 228392 6 May 20:42 1778089327270_m1.jpg\n-rw-r--r-- 1 lukas staff 162605 6 May 20:42 1778089329081_m2.jpg\n-rw-r--r-- 1 lukas staff 230328 6 May 20:42 1778089358286_m1.jpg\n-rw-r--r-- 1 lukas staff 162589 6 May 20:42 1778089360293_m2.jpg\n-rw-r--r-- 1 lukas staff 1038222 6 May 20:40 compact_monitor_1_1778089220643.mp4\n-rw-r--r-- 1 lukas staff 327159 6 May 20:40 compact_monitor_2_1778089221749.mp4\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","depth":4,"on_screen":true,"value":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 24992\ndrwxr-xr-x 66 lukas staff 2112 6 May 20:42 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\n-rw-r--r-- 1 lukas staff 228402 6 May 20:34 1778088862349_m1.jpg\n-rw-r--r-- 1 lukas staff 162494 6 May 20:34 1778088862922_m2.jpg\n-rw-r--r-- 1 lukas staff 228391 6 May 20:34 1778088895443_m1.jpg\n-rw-r--r-- 1 lukas staff 162695 6 May 20:34 1778088897069_m2.jpg\n-rw-r--r-- 1 lukas staff 228420 6 May 20:35 1778088926328_m1.jpg\n-rw-r--r-- 1 lukas staff 162684 6 May 20:35 1778088927793_m2.jpg\n-rw-r--r-- 1 lukas staff 228407 6 May 20:35 1778088957089_m1.jpg\n-rw-r--r-- 1 lukas staff 162545 6 May 20:35 1778088958635_m2.jpg\n-rw-r--r-- 1 lukas staff 228407 6 May 20:36 1778088987860_m1.jpg\n-rw-r--r-- 1 lukas staff 162483 6 May 20:36 1778088989374_m2.jpg\n-rw-r--r-- 1 lukas staff 228420 6 May 20:36 1778089018527_m1.jpg\n-rw-r--r-- 1 lukas staff 162536 6 May 20:37 1778089020270_m2.jpg\n-rw-r--r-- 1 lukas staff 228372 6 May 20:37 1778089049194_m1.jpg\n-rw-r--r-- 1 lukas staff 162683 6 May 20:37 1778089050974_m2.jpg\n-rw-r--r-- 1 lukas staff 228412 6 May 20:38 1778089079866_m1.jpg\n-rw-r--r-- 1 lukas staff 162494 6 May 20:38 1778089081721_m2.jpg\n-rw-r--r-- 1 lukas staff 228380 6 May 20:38 1778089110848_m1.jpg\n-rw-r--r-- 1 lukas staff 162606 6 May 20:38 1778089112768_m2.jpg\n-rw-r--r-- 1 lukas staff 228380 6 May 20:39 1778089141520_m1.jpg\n-rw-r--r-- 1 lukas staff 162611 6 May 20:39 1778089143498_m2.jpg\n-rw-r--r-- 1 lukas staff 228353 6 May 20:39 1778089172629_m1.jpg\n-rw-r--r-- 1 lukas staff 162480 6 May 20:39 1778089174323_m2.jpg\n-rw-r--r-- 1 lukas staff 228332 6 May 20:40 1778089203288_m1.jpg\n-rw-r--r-- 1 lukas staff 162502 6 May 20:40 1778089205370_m2.jpg\n-rw-r--r-- 1 lukas staff 228372 6 May 20:40 1778089234520_m1.jpg\n-rw-r--r-- 1 lukas staff 162571 6 May 20:40 1778089236266_m2.jpg\n-rw-r--r-- 1 lukas staff 228416 6 May 20:41 1778089265485_m1.jpg\n-rw-r--r-- 1 lukas staff 162636 6 May 20:41 1778089267383_m2.jpg\n-rw-r--r-- 1 lukas staff 228362 6 May 20:41 1778089296562_m1.jpg\n-rw-r--r-- 1 lukas staff 162564 6 May 20:41 1778089298295_m2.jpg\n-rw-r--r-- 1 lukas staff 228392 6 May 20:42 1778089327270_m1.jpg\n-rw-r--r-- 1 lukas staff 162605 6 May 20:42 1778089329081_m2.jpg\n-rw-r--r-- 1 lukas staff 1038222 6 May 20:40 compact_monitor_1_1778089220643.mp4\n-rw-r--r-- 1 lukas staff 327159 6 May 20:40 compact_monitor_2_1778089221749.mp4\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 25768\ndrwxr-xr-x 68 lukas staff 2176 6 May 20:42 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\n-rw-r--r-- 1 lukas staff 228402 6 May 20:34 1778088862349_m1.jpg\n-rw-r--r-- 1 lukas staff 162494 6 May 20:34 1778088862922_m2.jpg\n-rw-r--r-- 1 lukas staff 228391 6 May 20:34 1778088895443_m1.jpg\n-rw-r--r-- 1 lukas staff 162695 6 May 20:34 1778088897069_m2.jpg\n-rw-r--r-- 1 lukas staff 228420 6 May 20:35 1778088926328_m1.jpg\n-rw-r--r-- 1 lukas staff 162684 6 May 20:35 1778088927793_m2.jpg\n-rw-r--r-- 1 lukas staff 228407 6 May 20:35 1778088957089_m1.jpg\n-rw-r--r-- 1 lukas staff 162545 6 May 20:35 1778088958635_m2.jpg\n-rw-r--r-- 1 lukas staff 228407 6 May 20:36 1778088987860_m1.jpg\n-rw-r--r-- 1 lukas staff 162483 6 May 20:36 1778088989374_m2.jpg\n-rw-r--r-- 1 lukas staff 228420 6 May 20:36 1778089018527_m1.jpg\n-rw-r--r-- 1 lukas staff 162536 6 May 20:37 1778089020270_m2.jpg\n-rw-r--r-- 1 lukas staff 228372 6 May 20:37 1778089049194_m1.jpg\n-rw-r--r-- 1 lukas staff 162683 6 May 20:37 1778089050974_m2.jpg\n-rw-r--r-- 1 lukas staff 228412 6 May 20:38 1778089079866_m1.jpg\n-rw-r--r-- 1 lukas staff 162494 6 May 20:38 1778089081721_m2.jpg\n-rw-r--r-- 1 lukas staff 228380 6 May 20:38 1778089110848_m1.jpg\n-rw-r--r-- 1 lukas staff 162606 6 May 20:38 1778089112768_m2.jpg\n-rw-r--r-- 1 lukas staff 228380 6 May 20:39 1778089141520_m1.jpg\n-rw-r--r-- 1 lukas staff 162611 6 May 20:39 1778089143498_m2.jpg\n-rw-r--r-- 1 lukas staff 228353 6 May 20:39 1778089172629_m1.jpg\n-rw-r--r-- 1 lukas staff 162480 6 May 20:39 1778089174323_m2.jpg\n-rw-r--r-- 1 lukas staff 228332 6 May 20:40 1778089203288_m1.jpg\n-rw-r--r-- 1 lukas staff 162502 6 May 20:40 1778089205370_m2.jpg\n-rw-r--r-- 1 lukas staff 228372 6 May 20:40 1778089234520_m1.jpg\n-rw-r--r-- 1 lukas staff 162571 6 May 20:40 1778089236266_m2.jpg\n-rw-r--r-- 1 lukas staff 228416 6 May 20:41 1778089265485_m1.jpg\n-rw-r--r-- 1 lukas staff 162636 6 May 20:41 1778089267383_m2.jpg\n-rw-r--r-- 1 lukas staff 228362 6 May 20:41 1778089296562_m1.jpg\n-rw-r--r-- 1 lukas staff 162564 6 May 20:41 1778089298295_m2.jpg\n-rw-r--r-- 1 lukas staff 228392 6 May 20:42 1778089327270_m1.jpg\n-rw-r--r-- 1 lukas staff 162605 6 May 20:42 1778089329081_m2.jpg\n-rw-r--r-- 1 lukas staff 230328 6 May 20:42 1778089358286_m1.jpg\n-rw-r--r-- 1 lukas staff 162589 6 May 20:42 1778089360293_m2.jpg\n-rw-r--r-- 1 lukas staff 1038222 6 May 20:40 compact_monitor_1_1778089220643.mp4\n-rw-r--r-- 1 lukas staff 327159 6 May 20:40 compact_monitor_2_1778089221749.mp4\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","is_focused":true},{"role":"AXRadioButton","text":"DOCKER","depth":2,"bounds":{"left":0.0,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.004166667,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"DEV (docker)","depth":2,"bounds":{"left":0.16388889,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.16805555,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"APP (-zsh)","depth":2,"bounds":{"left":0.32777777,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.33194444,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.49166667,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.49583334,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"screenpipe\"","depth":2,"bounds":{"left":0.65555555,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.6597222,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.8194444,"top":0.05888889,"width":0.16388889,"height":0.026666667},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.82361114,"top":0.06333333,"width":0.011111111,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"⌥⌘1","depth":1,"bounds":{"left":0.9548611,"top":0.032222223,"width":0.03888889,"height":0.018888889},"on_screen":true,"automation_id":"_NS:8","role_description":"text"},{"role":"AXStaticText","text":"-zsh","depth":1,"bounds":{"left":0.48819444,"top":0.033333335,"width":0.022916667,"height":0.017777778},"on_screen":true,"role_description":"text"}]...
|
-5472190852642453105
|
2903862479982313089
|
idle
|
accessibility
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 24992
drwxr-xr-x 66 lukas staff 2112 6 May 20:42 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
-rw-r--r-- 1 lukas staff 228402 6 May 20:34 1778088862349_m1.jpg
-rw-r--r-- 1 lukas staff 162494 6 May 20:34 1778088862922_m2.jpg
-rw-r--r-- 1 lukas staff 228391 6 May 20:34 1778088895443_m1.jpg
-rw-r--r-- 1 lukas staff 162695 6 May 20:34 1778088897069_m2.jpg
-rw-r--r-- 1 lukas staff 228420 6 May 20:35 1778088926328_m1.jpg
-rw-r--r-- 1 lukas staff 162684 6 May 20:35 1778088927793_m2.jpg
-rw-r--r-- 1 lukas staff 228407 6 May 20:35 1778088957089_m1.jpg
-rw-r--r-- 1 lukas staff 162545 6 May 20:35 1778088958635_m2.jpg
-rw-r--r-- 1 lukas staff 228407 6 May 20:36 1778088987860_m1.jpg
-rw-r--r-- 1 lukas staff 162483 6 May 20:36 1778088989374_m2.jpg
-rw-r--r-- 1 lukas staff 228420 6 May 20:36 1778089018527_m1.jpg
-rw-r--r-- 1 lukas staff 162536 6 May 20:37 1778089020270_m2.jpg
-rw-r--r-- 1 lukas staff 228372 6 May 20:37 1778089049194_m1.jpg
-rw-r--r-- 1 lukas staff 162683 6 May 20:37 1778089050974_m2.jpg
-rw-r--r-- 1 lukas staff 228412 6 May 20:38 1778089079866_m1.jpg
-rw-r--r-- 1 lukas staff 162494 6 May 20:38 1778089081721_m2.jpg
-rw-r--r-- 1 lukas staff 228380 6 May 20:38 1778089110848_m1.jpg
-rw-r--r-- 1 lukas staff 162606 6 May 20:38 1778089112768_m2.jpg
-rw-r--r-- 1 lukas staff 228380 6 May 20:39 1778089141520_m1.jpg
-rw-r--r-- 1 lukas staff 162611 6 May 20:39 1778089143498_m2.jpg
-rw-r--r-- 1 lukas staff 228353 6 May 20:39 1778089172629_m1.jpg
-rw-r--r-- 1 lukas staff 162480 6 May 20:39 1778089174323_m2.jpg
-rw-r--r-- 1 lukas staff 228332 6 May 20:40 1778089203288_m1.jpg
-rw-r--r-- 1 lukas staff 162502 6 May 20:40 1778089205370_m2.jpg
-rw-r--r-- 1 lukas staff 228372 6 May 20:40 1778089234520_m1.jpg
-rw-r--r-- 1 lukas staff 162571 6 May 20:40 1778089236266_m2.jpg
-rw-r--r-- 1 lukas staff 228416 6 May 20:41 1778089265485_m1.jpg
-rw-r--r-- 1 lukas staff 162636 6 May 20:41 1778089267383_m2.jpg
-rw-r--r-- 1 lukas staff 228362 6 May 20:41 1778089296562_m1.jpg
-rw-r--r-- 1 lukas staff 162564 6 May 20:41 1778089298295_m2.jpg
-rw-r--r-- 1 lukas staff 228392 6 May 20:42 1778089327270_m1.jpg
-rw-r--r-- 1 lukas staff 162605 6 May 20:42 1778089329081_m2.jpg
-rw-r--r-- 1 lukas staff 1038222 6 May 20:40 compact_monitor_1_1778089220643.mp4
-rw-r--r-- 1 lukas staff 327159 6 May 20:40 compact_monitor_2_1778089221749.mp4
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 25768
drwxr-xr-x 68 lukas staff 2176 6 May 20:42 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
-rw-r--r-- 1 lukas staff 228402 6 May 20:34 1778088862349_m1.jpg
-rw-r--r-- 1 lukas staff 162494 6 May 20:34 1778088862922_m2.jpg
-rw-r--r-- 1 lukas staff 228391 6 May 20:34 1778088895443_m1.jpg
-rw-r--r-- 1 lukas staff 162695 6 May 20:34 1778088897069_m2.jpg
-rw-r--r-- 1 lukas staff 228420 6 May 20:35 1778088926328_m1.jpg
-rw-r--r-- 1 lukas staff 162684 6 May 20:35 1778088927793_m2.jpg
-rw-r--r-- 1 lukas staff 228407 6 May 20:35 1778088957089_m1.jpg
-rw-r--r-- 1 lukas staff 162545 6 May 20:35 1778088958635_m2.jpg
-rw-r--r-- 1 lukas staff 228407 6 May 20:36 1778088987860_m1.jpg
-rw-r--r-- 1 lukas staff 162483 6 May 20:36 1778088989374_m2.jpg
-rw-r--r-- 1 lukas staff 228420 6 May 20:36 1778089018527_m1.jpg
-rw-r--r-- 1 lukas staff 162536 6 May 20:37 1778089020270_m2.jpg
-rw-r--r-- 1 lukas staff 228372 6 May 20:37 1778089049194_m1.jpg
-rw-r--r-- 1 lukas staff 162683 6 May 20:37 1778089050974_m2.jpg
-rw-r--r-- 1 lukas staff 228412 6 May 20:38 1778089079866_m1.jpg
-rw-r--r-- 1 lukas staff 162494 6 May 20:38 1778089081721_m2.jpg
-rw-r--r-- 1 lukas staff 228380 6 May 20:38 1778089110848_m1.jpg
-rw-r--r-- 1 lukas staff 162606 6 May 20:38 1778089112768_m2.jpg
-rw-r--r-- 1 lukas staff 228380 6 May 20:39 1778089141520_m1.jpg
-rw-r--r-- 1 lukas staff 162611 6 May 20:39 1778089143498_m2.jpg
-rw-r--r-- 1 lukas staff 228353 6 May 20:39 1778089172629_m1.jpg
-rw-r--r-- 1 lukas staff 162480 6 May 20:39 1778089174323_m2.jpg
-rw-r--r-- 1 lukas staff 228332 6 May 20:40 1778089203288_m1.jpg
-rw-r--r-- 1 lukas staff 162502 6 May 20:40 1778089205370_m2.jpg
-rw-r--r-- 1 lukas staff 228372 6 May 20:40 1778089234520_m1.jpg
-rw-r--r-- 1 lukas staff 162571 6 May 20:40 1778089236266_m2.jpg
-rw-r--r-- 1 lukas staff 228416 6 May 20:41 1778089265485_m1.jpg
-rw-r--r-- 1 lukas staff 162636 6 May 20:41 1778089267383_m2.jpg
-rw-r--r-- 1 lukas staff 228362 6 May 20:41 1778089296562_m1.jpg
-rw-r--r-- 1 lukas staff 162564 6 May 20:41 1778089298295_m2.jpg
-rw-r--r-- 1 lukas staff 228392 6 May 20:42 1778089327270_m1.jpg
-rw-r--r-- 1 lukas staff 162605 6 May 20:42 1778089329081_m2.jpg
-rw-r--r-- 1 lukas staff 230328 6 May 20:42 1778089358286_m1.jpg
-rw-r--r-- 1 lukas staff 162589 6 May 20:42 1778089360293_m2.jpg
-rw-r--r-- 1 lukas staff 1038222 6 May 20:40 compact_monitor_1_1778089220643.mp4
-rw-r--r-- 1 lukas staff 327159 6 May 20:40 compact_monitor_2_1778089221749.mp4
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
91
|
8
|
5
|
2026-05-06T17:43:11.156783+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778089391156_m2.jpg...
|
iTerm2
|
-zsh
|
True
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 24992
drwxr-xr-x 66 lukas staff 2112 6 May 20:42 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
-rw-r--r-- 1 lukas staff 228402 6 May 20:34 1778088862349_m1.jpg
-rw-r--r-- 1 lukas staff 162494 6 May 20:34 1778088862922_m2.jpg
-rw-r--r-- 1 lukas staff 228391 6 May 20:34 1778088895443_m1.jpg
-rw-r--r-- 1 lukas staff 162695 6 May 20:34 1778088897069_m2.jpg
-rw-r--r-- 1 lukas staff 228420 6 May 20:35 1778088926328_m1.jpg
-rw-r--r-- 1 lukas staff 162684 6 May 20:35 1778088927793_m2.jpg
-rw-r--r-- 1 lukas staff 228407 6 May 20:35 1778088957089_m1.jpg
-rw-r--r-- 1 lukas staff 162545 6 May 20:35 1778088958635_m2.jpg
-rw-r--r-- 1 lukas staff 228407 6 May 20:36 1778088987860_m1.jpg
-rw-r--r-- 1 lukas staff 162483 6 May 20:36 1778088989374_m2.jpg
-rw-r--r-- 1 lukas staff 228420 6 May 20:36 1778089018527_m1.jpg
-rw-r--r-- 1 lukas staff 162536 6 May 20:37 1778089020270_m2.jpg
-rw-r--r-- 1 lukas staff 228372 6 May 20:37 1778089049194_m1.jpg
-rw-r--r-- 1 lukas staff 162683 6 May 20:37 1778089050974_m2.jpg
-rw-r--r-- 1 lukas staff 228412 6 May 20:38 1778089079866_m1.jpg
-rw-r--r-- 1 lukas staff 162494 6 May 20:38 1778089081721_m2.jpg
-rw-r--r-- 1 lukas staff 228380 6 May 20:38 1778089110848_m1.jpg
-rw-r--r-- 1 lukas staff 162606 6 May 20:38 1778089112768_m2.jpg
-rw-r--r-- 1 lukas staff 228380 6 May 20:39 1778089141520_m1.jpg
-rw-r--r-- 1 lukas staff 162611 6 May 20:39 1778089143498_m2.jpg
-rw-r--r-- 1 lukas staff 228353 6 May 20:39 1778089172629_m1.jpg
-rw-r--r-- 1 lukas staff 162480 6 May 20:39 1778089174323_m2.jpg
-rw-r--r-- 1 lukas staff 228332 6 May 20:40 1778089203288_m1.jpg
-rw-r--r-- 1 lukas staff 162502 6 May 20:40 1778089205370_m2.jpg
-rw-r--r-- 1 lukas staff 228372 6 May 20:40 1778089234520_m1.jpg
-rw-r--r-- 1 lukas staff 162571 6 May 20:40 1778089236266_m2.jpg
-rw-r--r-- 1 lukas staff 228416 6 May 20:41 1778089265485_m1.jpg
-rw-r--r-- 1 lukas staff 162636 6 May 20:41 1778089267383_m2.jpg
-rw-r--r-- 1 lukas staff 228362 6 May 20:41 1778089296562_m1.jpg
-rw-r--r-- 1 lukas staff 162564 6 May 20:41 1778089298295_m2.jpg
-rw-r--r-- 1 lukas staff 228392 6 May 20:42 1778089327270_m1.jpg
-rw-r--r-- 1 lukas staff 162605 6 May 20:42 1778089329081_m2.jpg
-rw-r--r-- 1 lukas staff 1038222 6 May 20:40 compact_monitor_1_1778089220643.mp4
-rw-r--r-- 1 lukas staff 327159 6 May 20:40 compact_monitor_2_1778089221749.mp4
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 25768
drwxr-xr-x 68 lukas staff 2176 6 May 20:42 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
-rw-r--r-- 1 lukas staff 228402 6 May 20:34 1778088862349_m1.jpg
-rw-r--r-- 1 lukas staff 162494 6 May 20:34 1778088862922_m2.jpg
-rw-r--r-- 1 lukas staff 228391 6 May 20:34 1778088895443_m1.jpg
-rw-r--r-- 1 lukas staff 162695 6 May 20:34 1778088897069_m2.jpg
-rw-r--r-- 1 lukas staff 228420 6 May 20:35 1778088926328_m1.jpg
-rw-r--r-- 1 lukas staff 162684 6 May 20:35 1778088927793_m2.jpg
-rw-r--r-- 1 lukas staff 228407 6 May 20:35 1778088957089_m1.jpg
-rw-r--r-- 1 lukas staff 162545 6 May 20:35 1778088958635_m2.jpg
-rw-r--r-- 1 lukas staff 228407 6 May 20:36 1778088987860_m1.jpg
-rw-r--r-- 1 lukas staff 162483 6 May 20:36 1778088989374_m2.jpg
-rw-r--r-- 1 lukas staff 228420 6 May 20:36 1778089018527_m1.jpg
-rw-r--r-- 1 lukas staff 162536 6 May 20:37 1778089020270_m2.jpg
-rw-r--r-- 1 lukas staff 228372 6 May 20:37 1778089049194_m1.jpg
-rw-r--r-- 1 lukas staff 162683 6 May 20:37 1778089050974_m2.jpg
-rw-r--r-- 1 lukas staff 228412 6 May 20:38 1778089079866_m1.jpg
-rw-r--r-- 1 lukas staff 162494 6 May 20:38 1778089081721_m2.jpg
-rw-r--r-- 1 lukas staff 228380 6 May 20:38 1778089110848_m1.jpg
-rw-r--r-- 1 lukas staff 162606 6 May 20:38 1778089112768_m2.jpg
-rw-r--r-- 1 lukas staff 228380 6 May 20:39 1778089141520_m1.jpg
-rw-r--r-- 1 lukas staff 162611 6 May 20:39 1778089143498_m2.jpg
-rw-r--r-- 1 lukas staff 228353 6 May 20:39 1778089172629_m1.jpg
-rw-r--r-- 1 lukas staff 162480 6 May 20:39 1778089174323_m2.jpg
-rw-r--r-- 1 lukas staff 228332 6 May 20:40 1778089203288_m1.jpg
-rw-r--r-- 1 lukas staff 162502 6 May 20:40 1778089205370_m2.jpg
-rw-r--r-- 1 lukas staff 228372 6 May 20:40 1778089234520_m1.jpg
-rw-r--r-- 1 lukas staff 162571 6 May 20:40 1778089236266_m2.jpg
-rw-r--r-- 1 lukas staff 228416 6 May 20:41 1778089265485_m1.jpg
-rw-r--r-- 1 lukas staff 162636 6 May 20:41 1778089267383_m2.jpg
-rw-r--r-- 1 lukas staff 228362 6 May 20:41 1778089296562_m1.jpg
-rw-r--r-- 1 lukas staff 162564 6 May 20:41 1778089298295_m2.jpg
-rw-r--r-- 1 lukas staff 228392 6 May 20:42 1778089327270_m1.jpg
-rw-r--r-- 1 lukas staff 162605 6 May 20:42 1778089329081_m2.jpg
-rw-r--r-- 1 lukas staff 230328 6 May 20:42 1778089358286_m1.jpg
-rw-r--r-- 1 lukas staff 162589 6 May 20:42 1778089360293_m2.jpg
-rw-r--r-- 1 lukas staff 1038222 6 May 20:40 compact_monitor_1_1778089220643.mp4
-rw-r--r-- 1 lukas staff 327159 6 May 20:40 compact_monitor_2_1778089221749.mp4
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 24992\ndrwxr-xr-x 66 lukas staff 2112 6 May 20:42 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\n-rw-r--r-- 1 lukas staff 228402 6 May 20:34 1778088862349_m1.jpg\n-rw-r--r-- 1 lukas staff 162494 6 May 20:34 1778088862922_m2.jpg\n-rw-r--r-- 1 lukas staff 228391 6 May 20:34 1778088895443_m1.jpg\n-rw-r--r-- 1 lukas staff 162695 6 May 20:34 1778088897069_m2.jpg\n-rw-r--r-- 1 lukas staff 228420 6 May 20:35 1778088926328_m1.jpg\n-rw-r--r-- 1 lukas staff 162684 6 May 20:35 1778088927793_m2.jpg\n-rw-r--r-- 1 lukas staff 228407 6 May 20:35 1778088957089_m1.jpg\n-rw-r--r-- 1 lukas staff 162545 6 May 20:35 1778088958635_m2.jpg\n-rw-r--r-- 1 lukas staff 228407 6 May 20:36 1778088987860_m1.jpg\n-rw-r--r-- 1 lukas staff 162483 6 May 20:36 1778088989374_m2.jpg\n-rw-r--r-- 1 lukas staff 228420 6 May 20:36 1778089018527_m1.jpg\n-rw-r--r-- 1 lukas staff 162536 6 May 20:37 1778089020270_m2.jpg\n-rw-r--r-- 1 lukas staff 228372 6 May 20:37 1778089049194_m1.jpg\n-rw-r--r-- 1 lukas staff 162683 6 May 20:37 1778089050974_m2.jpg\n-rw-r--r-- 1 lukas staff 228412 6 May 20:38 1778089079866_m1.jpg\n-rw-r--r-- 1 lukas staff 162494 6 May 20:38 1778089081721_m2.jpg\n-rw-r--r-- 1 lukas staff 228380 6 May 20:38 1778089110848_m1.jpg\n-rw-r--r-- 1 lukas staff 162606 6 May 20:38 1778089112768_m2.jpg\n-rw-r--r-- 1 lukas staff 228380 6 May 20:39 1778089141520_m1.jpg\n-rw-r--r-- 1 lukas staff 162611 6 May 20:39 1778089143498_m2.jpg\n-rw-r--r-- 1 lukas staff 228353 6 May 20:39 1778089172629_m1.jpg\n-rw-r--r-- 1 lukas staff 162480 6 May 20:39 1778089174323_m2.jpg\n-rw-r--r-- 1 lukas staff 228332 6 May 20:40 1778089203288_m1.jpg\n-rw-r--r-- 1 lukas staff 162502 6 May 20:40 1778089205370_m2.jpg\n-rw-r--r-- 1 lukas staff 228372 6 May 20:40 1778089234520_m1.jpg\n-rw-r--r-- 1 lukas staff 162571 6 May 20:40 1778089236266_m2.jpg\n-rw-r--r-- 1 lukas staff 228416 6 May 20:41 1778089265485_m1.jpg\n-rw-r--r-- 1 lukas staff 162636 6 May 20:41 1778089267383_m2.jpg\n-rw-r--r-- 1 lukas staff 228362 6 May 20:41 1778089296562_m1.jpg\n-rw-r--r-- 1 lukas staff 162564 6 May 20:41 1778089298295_m2.jpg\n-rw-r--r-- 1 lukas staff 228392 6 May 20:42 1778089327270_m1.jpg\n-rw-r--r-- 1 lukas staff 162605 6 May 20:42 1778089329081_m2.jpg\n-rw-r--r-- 1 lukas staff 1038222 6 May 20:40 compact_monitor_1_1778089220643.mp4\n-rw-r--r-- 1 lukas staff 327159 6 May 20:40 compact_monitor_2_1778089221749.mp4\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 25768\ndrwxr-xr-x 68 lukas staff 2176 6 May 20:42 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\n-rw-r--r-- 1 lukas staff 228402 6 May 20:34 1778088862349_m1.jpg\n-rw-r--r-- 1 lukas staff 162494 6 May 20:34 1778088862922_m2.jpg\n-rw-r--r-- 1 lukas staff 228391 6 May 20:34 1778088895443_m1.jpg\n-rw-r--r-- 1 lukas staff 162695 6 May 20:34 1778088897069_m2.jpg\n-rw-r--r-- 1 lukas staff 228420 6 May 20:35 1778088926328_m1.jpg\n-rw-r--r-- 1 lukas staff 162684 6 May 20:35 1778088927793_m2.jpg\n-rw-r--r-- 1 lukas staff 228407 6 May 20:35 1778088957089_m1.jpg\n-rw-r--r-- 1 lukas staff 162545 6 May 20:35 1778088958635_m2.jpg\n-rw-r--r-- 1 lukas staff 228407 6 May 20:36 1778088987860_m1.jpg\n-rw-r--r-- 1 lukas staff 162483 6 May 20:36 1778088989374_m2.jpg\n-rw-r--r-- 1 lukas staff 228420 6 May 20:36 1778089018527_m1.jpg\n-rw-r--r-- 1 lukas staff 162536 6 May 20:37 1778089020270_m2.jpg\n-rw-r--r-- 1 lukas staff 228372 6 May 20:37 1778089049194_m1.jpg\n-rw-r--r-- 1 lukas staff 162683 6 May 20:37 1778089050974_m2.jpg\n-rw-r--r-- 1 lukas staff 228412 6 May 20:38 1778089079866_m1.jpg\n-rw-r--r-- 1 lukas staff 162494 6 May 20:38 1778089081721_m2.jpg\n-rw-r--r-- 1 lukas staff 228380 6 May 20:38 1778089110848_m1.jpg\n-rw-r--r-- 1 lukas staff 162606 6 May 20:38 1778089112768_m2.jpg\n-rw-r--r-- 1 lukas staff 228380 6 May 20:39 1778089141520_m1.jpg\n-rw-r--r-- 1 lukas staff 162611 6 May 20:39 1778089143498_m2.jpg\n-rw-r--r-- 1 lukas staff 228353 6 May 20:39 1778089172629_m1.jpg\n-rw-r--r-- 1 lukas staff 162480 6 May 20:39 1778089174323_m2.jpg\n-rw-r--r-- 1 lukas staff 228332 6 May 20:40 1778089203288_m1.jpg\n-rw-r--r-- 1 lukas staff 162502 6 May 20:40 1778089205370_m2.jpg\n-rw-r--r-- 1 lukas staff 228372 6 May 20:40 1778089234520_m1.jpg\n-rw-r--r-- 1 lukas staff 162571 6 May 20:40 1778089236266_m2.jpg\n-rw-r--r-- 1 lukas staff 228416 6 May 20:41 1778089265485_m1.jpg\n-rw-r--r-- 1 lukas staff 162636 6 May 20:41 1778089267383_m2.jpg\n-rw-r--r-- 1 lukas staff 228362 6 May 20:41 1778089296562_m1.jpg\n-rw-r--r-- 1 lukas staff 162564 6 May 20:41 1778089298295_m2.jpg\n-rw-r--r-- 1 lukas staff 228392 6 May 20:42 1778089327270_m1.jpg\n-rw-r--r-- 1 lukas staff 162605 6 May 20:42 1778089329081_m2.jpg\n-rw-r--r-- 1 lukas staff 230328 6 May 20:42 1778089358286_m1.jpg\n-rw-r--r-- 1 lukas staff 162589 6 May 20:42 1778089360293_m2.jpg\n-rw-r--r-- 1 lukas staff 1038222 6 May 20:40 compact_monitor_1_1778089220643.mp4\n-rw-r--r-- 1 lukas staff 327159 6 May 20:40 compact_monitor_2_1778089221749.mp4\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","depth":4,"on_screen":true,"value":"Last login: Mon Apr 27 19:05:19 on ttys022\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\n\nPoetry could not find a pyproject.toml file in /Users/lukas or its parents\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe \n 17G\u0000\u0000\u0000\t/Users/lukas/.screenpipe\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*\n4.0K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/config.json\n6.7G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/data\n 11G\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite\n 32K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-shm\n 0B\u0000\u0000\u0000\t/Users/lukas/.screenpipe/db.sqlite-wal\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/pipes\n132K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log\n 96K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log\n 72K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log\n160K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log\n172K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log\n196K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log\n204K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log\n 64K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log\n352K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log\n668K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log\n280K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log\n176K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log\n272K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log\n 68K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log\n 76K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log\n596K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log\n388K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log\n 16K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/screenpipe_sync.sh\n 36K\u0000\u0000\u0000\t/Users/lukas/.screenpipe/sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 22520352\ndrwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .\ndrwx------+ 93 lukas staff 2976 6 May 19:02 ..\n-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store\ndrwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude\n-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json\ndrwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data\n-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite\n-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm\n-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal\ndrwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes\n-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log\n-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log\n-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log\n-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log\n-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log\n-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log\n-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log\n-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log\n-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log\n-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log\n-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log\n-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log\n-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log\n-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log\n-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log\n-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log\n-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log\n-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log\n-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh\n-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh \n#!/bin/bash\n# screenpipe_sync.sh\n# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).\n# Also copies the day's video/frame data folder to the NAS.\n#\n# Usage:\n# ./screenpipe_sync.sh # syncs yesterday (default)\n# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date\n# ./screenpipe_sync.sh today # syncs today so far\n#\n# Cron example (runs at 3am daily):\n# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1\n\nset -euo pipefail\n\n# ─── CONFIG ───────────────────────────────────────────────────────────────────\nDB_SRC=\"${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}\"\nNAS_MOUNT=\"${NAS_MOUNT:-/Volumes/screenpipe}\"\nNAS_DB=\"$NAS_MOUNT/archive.db\"\nNAS_DATA=\"$NAS_MOUNT/data\"\nLOG_FILE=\"$HOME/.screenpipe/sync.log\"\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── HELPERS ──────────────────────────────────────────────────────────────────\nSCRIPT_START=$(date +%s)\n\nlog() {\n local msg=\"[$(date '+%Y-%m-%d %H:%M:%S')] $*\"\n echo \"$msg\" | tee -a \"$LOG_FILE\"\n}\n\nstep() {\n local now=$(date +%s)\n local elapsed=$(( now - SCRIPT_START ))\n local min=$(( elapsed / 60 ))\n local sec=$(( elapsed % 60 ))\n printf \"\\n[+%02dm%02ds] ▶ %s\\n\" \"$min\" \"$sec\" \"$*\" | tee -a \"$LOG_FILE\"\n}\n\nrun_sqlite_heredoc() {\n local label=\"$1\"\n local sql=\"$2\"\n local start=$(date +%s)\n\n printf \" %-36s \" \"$label\"\n\n sqlite3 \"$DB_SRC\" <<< \"$sql\" &\n local pid=$!\n local spin=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')\n local i=0\n while kill -0 \"$pid\" 2>/dev/null; do\n printf \"\\r %-36s %s \" \"$label\" \"${spin[$i]}\"\n i=$(( (i + 1) % 10 ))\n sleep 0.2\n done\n wait \"$pid\"\n local rc=$?\n if [ $rc -ne 0 ]; then\n printf \"\\r %-36s ✗ FAILED\\n\" \"$label\" | tee -a \"$LOG_FILE\"\n exit $rc\n fi\n\n local dur=$(( $(date +%s) - start ))\n printf \"\\r %-36s ✓ %dm%02ds\\n\" \"$label\" \"$(( dur / 60 ))\" \"$(( dur % 60 ))\" | tee -a \"$LOG_FILE\"\n}\n\ncheck() {\n local label=\"$1\" got=\"$2\" expected=\"$3\"\n if [ \"$got\" -eq \"$expected\" ]; then\n printf \" %-20s %s / %s ✓\\n\" \"$label:\" \"$got\" \"$expected\"\n else\n printf \" %-20s %s / %s ✗ MISMATCH\\n\" \"$label:\" \"$got\" \"$expected\"\n fi\n}\n# ──────────────────────────────────────────────────────────────────────────────\n\n# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────\nif [ \"${1:-}\" = \"today\" ]; then\n TARGET_DATE=$(date +%Y-%m-%d)\nelif [ -n \"${1:-}\" ]; then\n TARGET_DATE=\"$1\"\n if ! [[ \"$TARGET_DATE\" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then\n echo \"ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday.\"\n exit 1\n fi\nelse\n TARGET_DATE=$(date -v-1d +%Y-%m-%d)\nfi\n\nlog \"========================================\"\nlog \"Screenpipe sync starting for: $TARGET_DATE\"\nlog \"========================================\"\n\n# ─── PREFLIGHT ────────────────────────────────────────────────────────────────\nstep \"Preflight checks\"\n\nif [ ! -f \"$DB_SRC\" ]; then\n log \"ERROR: Source DB not found at $DB_SRC\"; exit 1\nfi\nprintf \" %-20s %s (%s)\\n\" \"Source DB:\" \"OK\" \"$(du -sh \"$DB_SRC\" | cut -f1)\"\n\nif [ ! -d \"$NAS_MOUNT\" ]; then\n log \"ERROR: NAS not mounted at $NAS_MOUNT\"; exit 1\nfi\nprintf \" %-20s %s\\n\" \"NAS mount:\" \"OK $NAS_MOUNT\"\n\n# Check if DB already synced for this date\nDB_ALREADY_SYNCED=false\nif [ -f \"$NAS_DB\" ]; then\n EXISTING=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\" 2>/dev/null || echo \"0\")\n if [ \"$EXISTING\" -gt \"0\" ]; then\n log \"Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n else\n printf \" %-20s %s (%s)\\n\" \"Archive DB:\" \"exists\" \"$(du -sh \"$NAS_DB\" | cut -f1)\"\n fi\nelse\n printf \" %-20s %s\\n\" \"Archive DB:\" \"will be created\"\nfi\n\n# Source data dir for this date\nDATA_SRC=\"$HOME/.screenpipe/data/data/$TARGET_DATE\"\nif [ -d \"$DATA_SRC\" ]; then\n DATA_SIZE=$(du -sh \"$DATA_SRC\" | cut -f1)\n DATA_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n printf \" %-20s %s (%s files, %s)\\n\" \"Data dir:\" \"OK\" \"$DATA_FILES\" \"$DATA_SIZE\"\nelse\n printf \" %-20s %s\\n\" \"Data dir:\" \"not found — skipping file copy\"\nfi\n\n# ─── DB SYNC ──────────────────────────────────────────────────────────────────\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────\n step \"Counting source rows for $TARGET_DATE\"\n\n SRC_FRAMES=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_ELEMENTS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_UI=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n SRC_OCR=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n SRC_MEETINGS=$(sqlite3 \"$DB_SRC\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';\")\n\n printf \" %-20s %s\\n\" \"frames:\" \"$SRC_FRAMES\"\n printf \" %-20s %s\\n\" \"elements:\" \"$SRC_ELEMENTS\"\n printf \" %-20s %s\\n\" \"ui_events:\" \"$SRC_UI\"\n printf \" %-20s %s\\n\" \"ocr_text:\" \"$SRC_OCR\"\n printf \" %-20s %s\\n\" \"meetings:\" \"$SRC_MEETINGS\"\n\n if [ \"$SRC_FRAMES\" -eq \"0\" ]; then\n log \"No frames found for $TARGET_DATE — skipping DB sync\"\n DB_ALREADY_SYNCED=true\n fi\n\nfi\n\nif [ \"$DB_ALREADY_SYNCED\" = false ]; then\n\n # ─── INIT TABLES ──────────────────────────────────────────────────────────\n step \"Initialising tables, indexes, FTS\"\n\n run_sqlite_heredoc \"creating tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;\nCREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating indexes\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);\nCREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);\nCREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);\nCREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);\nCREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"creating FTS tables\" \"\nATTACH '$NAS_DB' AS nas;\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(\n text, role, frame_id UNINDEXED,\n content='elements', content_rowid='id', tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(\n full_text, app_name, window_name, browser_url, id UNINDEXED,\n tokenize='unicode61'\n);\nCREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(\n text_content,\n app_name,\n window_title,\n element_name,\n content='ui_events',\n content_rowid='id',\n tokenize='unicode61'\n);\nDETACH nas;\n\"\n\n # ─── SYNC DATA ────────────────────────────────────────────────────────────\n step \"Syncing data for $TARGET_DATE\"\n\n run_sqlite_heredoc \"video_chunks\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.video_chunks\n SELECT * FROM main.video_chunks\n WHERE id IN (\n SELECT DISTINCT video_chunk_id FROM main.frames\n WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL\n );\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames ($SRC_FRAMES rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.frames\n SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ocr_text ($SRC_OCR rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ocr_text\n SELECT o.* FROM main.ocr_text o\n JOIN main.frames f ON o.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events ($SRC_UI rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.ui_events\n SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"elements ($SRC_ELEMENTS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.elements\n SELECT e.* FROM main.elements e\n JOIN main.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"meetings ($SRC_MEETINGS rows)\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT OR IGNORE INTO nas.meetings\n SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';\nDETACH nas;\n\"\n\n # ─── FTS UPDATE ───────────────────────────────────────────────────────────\n step \"Updating FTS indexes\"\n\n run_sqlite_heredoc \"elements_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.elements_fts(rowid, text, role)\n SELECT e.id, e.text, e.role\n FROM nas.elements e\n JOIN nas.frames f ON e.frame_id = f.id\n WHERE date(f.timestamp) = '$TARGET_DATE'\n AND e.text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"frames_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)\n SELECT id, full_text, app_name, window_name, browser_url, id\n FROM nas.frames\n WHERE date(timestamp) = '$TARGET_DATE'\n AND full_text IS NOT NULL;\nDETACH nas;\n\"\n\n run_sqlite_heredoc \"ui_events_fts\" \"\nATTACH '$NAS_DB' AS nas;\nINSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)\n SELECT id, text_content, app_name, window_title, element_name\n FROM nas.ui_events\n WHERE date(timestamp) = '$TARGET_DATE'\n AND text_content IS NOT NULL;\nDETACH nas;\n\"\n\n # ─── VERIFY DB ────────────────────────────────────────────────────────────\n step \"Verifying DB\"\n\n V_FRAMES=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';\")\n V_ELEMENTS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_UI=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';\")\n V_OCR=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');\")\n V_MEETINGS=$(sqlite3 \"$NAS_DB\" \"SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';\")\n\n check \"frames\" \"$V_FRAMES\" \"$SRC_FRAMES\"\n check \"elements\" \"$V_ELEMENTS\" \"$SRC_ELEMENTS\"\n check \"ui_events\" \"$V_UI\" \"$SRC_UI\"\n check \"ocr_text\" \"$V_OCR\" \"$SRC_OCR\"\n check \"meetings\" \"$V_MEETINGS\" \"$SRC_MEETINGS\"\n\nfi\n\n# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────\n# Always runs regardless of DB sync status\nstep \"Copying data folder for $TARGET_DATE\"\n\nif [ -d \"$DATA_SRC\" ]; then\n mkdir -p \"$NAS_DATA/$TARGET_DATE\"\n RSYNC_START=$(date +%s)\n printf \" %-36s \" \"rsync $TARGET_DATE/ → NAS\"\n rsync -a --ignore-existing \\\n \"$DATA_SRC/\" \\\n \"$NAS_DATA/$TARGET_DATE/\" \\\n 2>>\"$LOG_FILE\"\n RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))\n COPIED_FILES=$(ls \"$NAS_DATA/$TARGET_DATE\" | wc -l | tr -d ' ')\n SRC_FILES=$(ls \"$DATA_SRC\" | wc -l | tr -d ' ')\n COPIED_SIZE=$(du -sh \"$NAS_DATA/$TARGET_DATE\" | cut -f1)\n if [ \"$COPIED_FILES\" -eq \"$SRC_FILES\" ]; then\n printf \"\\r %-36s ✓ %dm%02ds (%s files, %s)\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \\\n \"$(( RSYNC_DUR / 60 ))\" \"$(( RSYNC_DUR % 60 ))\" \\\n \"$COPIED_FILES\" \"$COPIED_SIZE\" | tee -a \"$LOG_FILE\"\n else\n printf \"\\r %-36s ✗ %s / %s files\\n\" \\\n \"rsync $TARGET_DATE/ → NAS\" \"$COPIED_FILES\" \"$SRC_FILES\" | tee -a \"$LOG_FILE\"\n fi\nelse\n printf \" %-36s %s\\n\" \"rsync $TARGET_DATE/ → NAS\" \"skipped (no source dir)\"\nfi\n\n# ─── SUMMARY ──────────────────────────────────────────────────────────────────\nTOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))\nDB_SIZE=$(du -sh \"$NAS_DB\" | cut -f1)\n\necho \"\"\nlog \"Archive DB size: $DB_SIZE\"\nlog \"Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s\"\nlog \"Sync complete for $TARGET_DATE\"\nlog \"========================================\"\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll \ntotal 0\ndrwxr-xr-x 2 lukas staff 64 6 May 20:22 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 9424\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 .\ndrwx------+ 94 lukas staff 3008 6 May 20:27 ..\ndrwxr-xr-x 5 lukas staff 160 6 May 20:28 data\n-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop\nscreenpipe stopped\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll\ntotal 21216\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 .\ndrwx------+ 94 lukas staff 3008 6 May 20:29 ..\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 data\n-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite\n-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm\n-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal\ndrwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes\n-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll\ntotal 3056\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 .\ndrwxr-xr-x 8 lukas staff 256 6 May 20:32 ..\n-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4\n-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4\n-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4\n-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4\n-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4\n-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 data\ndrwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll\ntotal 0\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 .\ndrwxr-xr-x 18 lukas staff 576 6 May 20:31 ..\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06 \nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 17432\ndrwxr-xr-x 57 lukas staff 1824 6 May 20:32 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg\n-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg\n-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg\n-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg\n-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg\n-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg\n-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg\n-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg\n-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg\n-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg\n-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg\n-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg\n-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg\n-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg\n-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg\n-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg\n-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg\n-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg\n-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg\n-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg\n-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg\n-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg\n-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg\n-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg\n-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 24992\ndrwxr-xr-x 66 lukas staff 2112 6 May 20:42 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\n-rw-r--r-- 1 lukas staff 228402 6 May 20:34 1778088862349_m1.jpg\n-rw-r--r-- 1 lukas staff 162494 6 May 20:34 1778088862922_m2.jpg\n-rw-r--r-- 1 lukas staff 228391 6 May 20:34 1778088895443_m1.jpg\n-rw-r--r-- 1 lukas staff 162695 6 May 20:34 1778088897069_m2.jpg\n-rw-r--r-- 1 lukas staff 228420 6 May 20:35 1778088926328_m1.jpg\n-rw-r--r-- 1 lukas staff 162684 6 May 20:35 1778088927793_m2.jpg\n-rw-r--r-- 1 lukas staff 228407 6 May 20:35 1778088957089_m1.jpg\n-rw-r--r-- 1 lukas staff 162545 6 May 20:35 1778088958635_m2.jpg\n-rw-r--r-- 1 lukas staff 228407 6 May 20:36 1778088987860_m1.jpg\n-rw-r--r-- 1 lukas staff 162483 6 May 20:36 1778088989374_m2.jpg\n-rw-r--r-- 1 lukas staff 228420 6 May 20:36 1778089018527_m1.jpg\n-rw-r--r-- 1 lukas staff 162536 6 May 20:37 1778089020270_m2.jpg\n-rw-r--r-- 1 lukas staff 228372 6 May 20:37 1778089049194_m1.jpg\n-rw-r--r-- 1 lukas staff 162683 6 May 20:37 1778089050974_m2.jpg\n-rw-r--r-- 1 lukas staff 228412 6 May 20:38 1778089079866_m1.jpg\n-rw-r--r-- 1 lukas staff 162494 6 May 20:38 1778089081721_m2.jpg\n-rw-r--r-- 1 lukas staff 228380 6 May 20:38 1778089110848_m1.jpg\n-rw-r--r-- 1 lukas staff 162606 6 May 20:38 1778089112768_m2.jpg\n-rw-r--r-- 1 lukas staff 228380 6 May 20:39 1778089141520_m1.jpg\n-rw-r--r-- 1 lukas staff 162611 6 May 20:39 1778089143498_m2.jpg\n-rw-r--r-- 1 lukas staff 228353 6 May 20:39 1778089172629_m1.jpg\n-rw-r--r-- 1 lukas staff 162480 6 May 20:39 1778089174323_m2.jpg\n-rw-r--r-- 1 lukas staff 228332 6 May 20:40 1778089203288_m1.jpg\n-rw-r--r-- 1 lukas staff 162502 6 May 20:40 1778089205370_m2.jpg\n-rw-r--r-- 1 lukas staff 228372 6 May 20:40 1778089234520_m1.jpg\n-rw-r--r-- 1 lukas staff 162571 6 May 20:40 1778089236266_m2.jpg\n-rw-r--r-- 1 lukas staff 228416 6 May 20:41 1778089265485_m1.jpg\n-rw-r--r-- 1 lukas staff 162636 6 May 20:41 1778089267383_m2.jpg\n-rw-r--r-- 1 lukas staff 228362 6 May 20:41 1778089296562_m1.jpg\n-rw-r--r-- 1 lukas staff 162564 6 May 20:41 1778089298295_m2.jpg\n-rw-r--r-- 1 lukas staff 228392 6 May 20:42 1778089327270_m1.jpg\n-rw-r--r-- 1 lukas staff 162605 6 May 20:42 1778089329081_m2.jpg\n-rw-r--r-- 1 lukas staff 1038222 6 May 20:40 compact_monitor_1_1778089220643.mp4\n-rw-r--r-- 1 lukas staff 327159 6 May 20:40 compact_monitor_2_1778089221749.mp4\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll\ntotal 25768\ndrwxr-xr-x 68 lukas staff 2176 6 May 20:42 .\ndrwxr-xr-x 3 lukas staff 96 6 May 20:27 ..\n-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg\n-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg\n-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg\n-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg\n-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg\n-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg\n-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg\n-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg\n-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg\n-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg\n-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg\n-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg\n-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg\n-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg\n-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg\n-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg\n-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg\n-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg\n-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg\n-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg\n-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg\n-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg\n-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg\n-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg\n-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg\n-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg\n-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg\n-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg\n-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg\n-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg\n-rw-r--r-- 1 lukas staff 228402 6 May 20:34 1778088862349_m1.jpg\n-rw-r--r-- 1 lukas staff 162494 6 May 20:34 1778088862922_m2.jpg\n-rw-r--r-- 1 lukas staff 228391 6 May 20:34 1778088895443_m1.jpg\n-rw-r--r-- 1 lukas staff 162695 6 May 20:34 1778088897069_m2.jpg\n-rw-r--r-- 1 lukas staff 228420 6 May 20:35 1778088926328_m1.jpg\n-rw-r--r-- 1 lukas staff 162684 6 May 20:35 1778088927793_m2.jpg\n-rw-r--r-- 1 lukas staff 228407 6 May 20:35 1778088957089_m1.jpg\n-rw-r--r-- 1 lukas staff 162545 6 May 20:35 1778088958635_m2.jpg\n-rw-r--r-- 1 lukas staff 228407 6 May 20:36 1778088987860_m1.jpg\n-rw-r--r-- 1 lukas staff 162483 6 May 20:36 1778088989374_m2.jpg\n-rw-r--r-- 1 lukas staff 228420 6 May 20:36 1778089018527_m1.jpg\n-rw-r--r-- 1 lukas staff 162536 6 May 20:37 1778089020270_m2.jpg\n-rw-r--r-- 1 lukas staff 228372 6 May 20:37 1778089049194_m1.jpg\n-rw-r--r-- 1 lukas staff 162683 6 May 20:37 1778089050974_m2.jpg\n-rw-r--r-- 1 lukas staff 228412 6 May 20:38 1778089079866_m1.jpg\n-rw-r--r-- 1 lukas staff 162494 6 May 20:38 1778089081721_m2.jpg\n-rw-r--r-- 1 lukas staff 228380 6 May 20:38 1778089110848_m1.jpg\n-rw-r--r-- 1 lukas staff 162606 6 May 20:38 1778089112768_m2.jpg\n-rw-r--r-- 1 lukas staff 228380 6 May 20:39 1778089141520_m1.jpg\n-rw-r--r-- 1 lukas staff 162611 6 May 20:39 1778089143498_m2.jpg\n-rw-r--r-- 1 lukas staff 228353 6 May 20:39 1778089172629_m1.jpg\n-rw-r--r-- 1 lukas staff 162480 6 May 20:39 1778089174323_m2.jpg\n-rw-r--r-- 1 lukas staff 228332 6 May 20:40 1778089203288_m1.jpg\n-rw-r--r-- 1 lukas staff 162502 6 May 20:40 1778089205370_m2.jpg\n-rw-r--r-- 1 lukas staff 228372 6 May 20:40 1778089234520_m1.jpg\n-rw-r--r-- 1 lukas staff 162571 6 May 20:40 1778089236266_m2.jpg\n-rw-r--r-- 1 lukas staff 228416 6 May 20:41 1778089265485_m1.jpg\n-rw-r--r-- 1 lukas staff 162636 6 May 20:41 1778089267383_m2.jpg\n-rw-r--r-- 1 lukas staff 228362 6 May 20:41 1778089296562_m1.jpg\n-rw-r--r-- 1 lukas staff 162564 6 May 20:41 1778089298295_m2.jpg\n-rw-r--r-- 1 lukas staff 228392 6 May 20:42 1778089327270_m1.jpg\n-rw-r--r-- 1 lukas staff 162605 6 May 20:42 1778089329081_m2.jpg\n-rw-r--r-- 1 lukas staff 230328 6 May 20:42 1778089358286_m1.jpg\n-rw-r--r-- 1 lukas staff 162589 6 May 20:42 1778089360293_m2.jpg\n-rw-r--r-- 1 lukas staff 1038222 6 May 20:40 compact_monitor_1_1778089220643.mp4\n-rw-r--r-- 1 lukas staff 327159 6 May 20:40 compact_monitor_2_1778089221749.mp4\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $","is_focused":true},{"role":"AXRadioButton","text":"DOCKER","depth":2,"bounds":{"left":0.27027926,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.27227393,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"DEV (docker)","depth":2,"bounds":{"left":0.3487367,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.35073137,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"APP (-zsh)","depth":2,"bounds":{"left":0.42719415,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.42918882,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.5056516,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.50764626,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"screenpipe\"","depth":2,"bounds":{"left":0.58410907,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.58610374,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.6625665,"top":1.0,"width":0.078457445,"height":-0.042298436},"on_screen":true,"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.66456115,"top":1.0,"width":0.005319149,"height":-0.04549086},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"⌥⌘1","depth":1,"bounds":{"left":0.7273936,"top":1.0,"width":0.01861702,"height":-0.023144484},"on_screen":true,"automation_id":"_NS:8","role_description":"text"},{"role":"AXStaticText","text":"-zsh","depth":1,"bounds":{"left":0.50398934,"top":1.0,"width":0.010970744,"height":-0.02394259},"on_screen":true,"role_description":"text"}]...
|
-5472190852642453105
|
2903862479982313089
|
idle
|
accessibility
|
NULL
|
Last login: Mon Apr 27 19:05:19 on ttys022
Poetry Last login: Mon Apr 27 19:05:19 on ttys022
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
Poetry could not find a pyproject.toml file in /Users/lukas or its parents
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe
17G /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ du -sh ~/.screenpipe/*
4.0K /Users/lukas/.screenpipe/config.json
6.7G /Users/lukas/.screenpipe/data
11G /Users/lukas/.screenpipe/db.sqlite
32K /Users/lukas/.screenpipe/db.sqlite-shm
0B /Users/lukas/.screenpipe/db.sqlite-wal
36K /Users/lukas/.screenpipe/pipes
132K /Users/lukas/.screenpipe/screenpipe.2026-04-09.0.log
96K /Users/lukas/.screenpipe/screenpipe.2026-04-11.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-12.0.log
72K /Users/lukas/.screenpipe/screenpipe.2026-04-13.0.log
160K /Users/lukas/.screenpipe/screenpipe.2026-04-14.0.log
172K /Users/lukas/.screenpipe/screenpipe.2026-04-15.0.log
196K /Users/lukas/.screenpipe/screenpipe.2026-04-16.0.log
204K /Users/lukas/.screenpipe/screenpipe.2026-04-17.0.log
64K /Users/lukas/.screenpipe/screenpipe.2026-04-18.0.log
352K /Users/lukas/.screenpipe/screenpipe.2026-04-20.0.log
668K /Users/lukas/.screenpipe/screenpipe.2026-04-21.0.log
280K /Users/lukas/.screenpipe/screenpipe.2026-04-22.0.log
176K /Users/lukas/.screenpipe/screenpipe.2026-04-23.0.log
272K /Users/lukas/.screenpipe/screenpipe.2026-04-24.0.log
68K /Users/lukas/.screenpipe/screenpipe.2026-04-25.0.log
76K /Users/lukas/.screenpipe/screenpipe.2026-04-26.0.log
596K /Users/lukas/.screenpipe/screenpipe.2026-04-27.0.log
388K /Users/lukas/.screenpipe/screenpipe.2026-04-28.0.log
16K /Users/lukas/.screenpipe/screenpipe_sync.sh
36K /Users/lukas/.screenpipe/sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22520352
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 6 May 19:02 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11526176768 6 May 18:58 db.sqlite
-rw-r--r--@ 1 lukas staff 32768 6 May 18:58 db.sqlite-shm
-rw-r--r--@ 1 lukas staff 0 6 May 18:58 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34823 6 May 18:58 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 9424
drwxr-xr-x 8 lukas staff 256 6 May 20:27 .
drwx------+ 94 lukas staff 3008 6 May 20:27 ..
drwxr-xr-x 5 lukas staff 160 6 May 20:28 data
-rw-r--r-- 1 lukas staff 581632 6 May 20:27 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:27 db.sqlite-shm
-rw-r--r-- 1 lukas staff 3312512 6 May 20:28 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 9566 6 May 20:28 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ sp-stop
screenpipe stopped
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 21216
drwxr-xr-x 8 lukas staff 256 6 May 20:32 .
drwx------+ 94 lukas staff 3008 6 May 20:29 ..
drwxr-xr-x 18 lukas staff 576 6 May 20:31 data
-rw-r--r-- 1 lukas staff 8708096 6 May 20:31 db.sqlite
-rw-r--r-- 1 lukas staff 32768 6 May 20:32 db.sqlite-shm
-rw-r--r-- 1 lukas staff 1697472 6 May 20:32 db.sqlite-wal
drwxr-xr-x 8 lukas staff 256 6 May 20:27 pipes
-rw-r--r-- 1 lukas staff 19041 6 May 20:32 screenpipe.2026-05-06.0.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ ll
total 3056
drwxr-xr-x 18 lukas staff 576 6 May 20:31 .
drwxr-xr-x 8 lukas staff 256 6 May 20:32 ..
-rw-r--r-- 1 lukas staff 210738 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 218037 6 May 20:28 MacBook Pro Microphone (input)_2026-05-06_17-28-19.mp4
-rw-r--r-- 1 lukas staff 216171 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-28-49.mp4
-rw-r--r-- 1 lukas staff 216193 6 May 20:29 MacBook Pro Microphone (input)_2026-05-06_17-29-19.mp4
-rw-r--r-- 1 lukas staff 209772 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 215405 6 May 20:30 MacBook Pro Microphone (input)_2026-05-06_17-30-18.mp4
-rw-r--r-- 1 lukas staff 205064 6 May 20:31 MacBook Pro Microphone (input)_2026-05-06_17-30-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-27-47.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:28 System Audio (output)_2026-05-06_17-28-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-28-50.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:29 System Audio (output)_2026-05-06_17-29-20.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-29-49.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:30 System Audio (output)_2026-05-06_17-30-19.mp4
-rw-r--r-- 1 lukas staff 4620 6 May 20:31 System Audio (output)_2026-05-06_17-30-47.mp4
drwxr-xr-x 3 lukas staff 96 6 May 20:27 data
drwxr-xr-x 2 lukas staff 64 6 May 20:29 pending-transcriptions
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd data
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ ll
total 0
drwxr-xr-x 3 lukas staff 96 6 May 20:27 .
drwxr-xr-x 18 lukas staff 576 6 May 20:31 ..
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd 2026-05-06
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 17432
drwxr-xr-x 57 lukas staff 1824 6 May 20:32 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 232466 6 May 20:27 1778088456772_m1.jpg
-rw-r--r-- 1 lukas staff 152554 6 May 20:27 1778088457434_m2.jpg
-rw-r--r-- 1 lukas staff 181543 6 May 20:27 1778088466571_m1.jpg
-rw-r--r-- 1 lukas staff 126979 6 May 20:27 1778088478583_m1.jpg
-rw-r--r-- 1 lukas staff 152544 6 May 20:28 1778088491264_m2.jpg
-rw-r--r-- 1 lukas staff 166250 6 May 20:28 1778088503148_m1.jpg
-rw-r--r-- 1 lukas staff 152522 6 May 20:28 1778088503179_m2.jpg
-rw-r--r-- 1 lukas staff 159999 6 May 20:28 1778088534192_m1.jpg
-rw-r--r-- 1 lukas staff 152579 6 May 20:28 1778088534522_m2.jpg
-rw-r--r-- 1 lukas staff 155560 6 May 20:29 1778088564250_m1.jpg
-rw-r--r-- 1 lukas staff 124040 6 May 20:29 1778088564930_m2.jpg
-rw-r--r-- 1 lukas staff 121232 6 May 20:29 1778088570551_m2.jpg
-rw-r--r-- 1 lukas staff 157568 6 May 20:29 1778088570945_m1.jpg
-rw-r--r-- 1 lukas staff 157625 6 May 20:29 1778088581767_m1.jpg
-rw-r--r-- 1 lukas staff 119295 6 May 20:29 1778088581767_m2.jpg
-rw-r--r-- 1 lukas staff 157529 6 May 20:29 1778088584166_m1.jpg
-rw-r--r-- 1 lukas staff 119415 6 May 20:29 1778088585022_m2.jpg
-rw-r--r-- 1 lukas staff 157483 6 May 20:29 1778088586312_m1.jpg
-rw-r--r-- 1 lukas staff 119430 6 May 20:29 1778088586786_m2.jpg
-rw-r--r-- 1 lukas staff 157657 6 May 20:29 1778088588816_m1.jpg
-rw-r--r-- 1 lukas staff 121321 6 May 20:29 1778088589524_m2.jpg
-rw-r--r-- 1 lukas staff 112106 6 May 20:30 1778088603330_m2.jpg
-rw-r--r-- 1 lukas staff 157634 6 May 20:30 1778088604117_m1.jpg
-rw-r--r-- 1 lukas staff 152205 6 May 20:30 1778088608499_m2.jpg
-rw-r--r-- 1 lukas staff 157651 6 May 20:30 1778088609502_m1.jpg
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 24992
drwxr-xr-x 66 lukas staff 2112 6 May 20:42 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
-rw-r--r-- 1 lukas staff 228402 6 May 20:34 1778088862349_m1.jpg
-rw-r--r-- 1 lukas staff 162494 6 May 20:34 1778088862922_m2.jpg
-rw-r--r-- 1 lukas staff 228391 6 May 20:34 1778088895443_m1.jpg
-rw-r--r-- 1 lukas staff 162695 6 May 20:34 1778088897069_m2.jpg
-rw-r--r-- 1 lukas staff 228420 6 May 20:35 1778088926328_m1.jpg
-rw-r--r-- 1 lukas staff 162684 6 May 20:35 1778088927793_m2.jpg
-rw-r--r-- 1 lukas staff 228407 6 May 20:35 1778088957089_m1.jpg
-rw-r--r-- 1 lukas staff 162545 6 May 20:35 1778088958635_m2.jpg
-rw-r--r-- 1 lukas staff 228407 6 May 20:36 1778088987860_m1.jpg
-rw-r--r-- 1 lukas staff 162483 6 May 20:36 1778088989374_m2.jpg
-rw-r--r-- 1 lukas staff 228420 6 May 20:36 1778089018527_m1.jpg
-rw-r--r-- 1 lukas staff 162536 6 May 20:37 1778089020270_m2.jpg
-rw-r--r-- 1 lukas staff 228372 6 May 20:37 1778089049194_m1.jpg
-rw-r--r-- 1 lukas staff 162683 6 May 20:37 1778089050974_m2.jpg
-rw-r--r-- 1 lukas staff 228412 6 May 20:38 1778089079866_m1.jpg
-rw-r--r-- 1 lukas staff 162494 6 May 20:38 1778089081721_m2.jpg
-rw-r--r-- 1 lukas staff 228380 6 May 20:38 1778089110848_m1.jpg
-rw-r--r-- 1 lukas staff 162606 6 May 20:38 1778089112768_m2.jpg
-rw-r--r-- 1 lukas staff 228380 6 May 20:39 1778089141520_m1.jpg
-rw-r--r-- 1 lukas staff 162611 6 May 20:39 1778089143498_m2.jpg
-rw-r--r-- 1 lukas staff 228353 6 May 20:39 1778089172629_m1.jpg
-rw-r--r-- 1 lukas staff 162480 6 May 20:39 1778089174323_m2.jpg
-rw-r--r-- 1 lukas staff 228332 6 May 20:40 1778089203288_m1.jpg
-rw-r--r-- 1 lukas staff 162502 6 May 20:40 1778089205370_m2.jpg
-rw-r--r-- 1 lukas staff 228372 6 May 20:40 1778089234520_m1.jpg
-rw-r--r-- 1 lukas staff 162571 6 May 20:40 1778089236266_m2.jpg
-rw-r--r-- 1 lukas staff 228416 6 May 20:41 1778089265485_m1.jpg
-rw-r--r-- 1 lukas staff 162636 6 May 20:41 1778089267383_m2.jpg
-rw-r--r-- 1 lukas staff 228362 6 May 20:41 1778089296562_m1.jpg
-rw-r--r-- 1 lukas staff 162564 6 May 20:41 1778089298295_m2.jpg
-rw-r--r-- 1 lukas staff 228392 6 May 20:42 1778089327270_m1.jpg
-rw-r--r-- 1 lukas staff 162605 6 May 20:42 1778089329081_m2.jpg
-rw-r--r-- 1 lukas staff 1038222 6 May 20:40 compact_monitor_1_1778089220643.mp4
-rw-r--r-- 1 lukas staff 327159 6 May 20:40 compact_monitor_2_1778089221749.mp4
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $ ll
total 25768
drwxr-xr-x 68 lukas staff 2176 6 May 20:42 .
drwxr-xr-x 3 lukas staff 96 6 May 20:27 ..
-rw-r--r-- 1 lukas staff 163575 6 May 20:30 1778088623310_m2.jpg
-rw-r--r-- 1 lukas staff 173535 6 May 20:30 1778088630735_m1.jpg
-rw-r--r-- 1 lukas staff 162111 6 May 20:30 1778088633155_m2.jpg
-rw-r--r-- 1 lukas staff 173763 6 May 20:30 1778088633901_m1.jpg
-rw-r--r-- 1 lukas staff 153966 6 May 20:30 1778088637729_m1.jpg
-rw-r--r-- 1 lukas staff 181815 6 May 20:30 1778088640280_m2.jpg
-rw-r--r-- 1 lukas staff 158733 6 May 20:30 1778088641897_m1.jpg
-rw-r--r-- 1 lukas staff 205244 6 May 20:30 1778088645543_m2.jpg
-rw-r--r-- 1 lukas staff 158969 6 May 20:30 1778088647024_m1.jpg
-rw-r--r-- 1 lukas staff 185029 6 May 20:30 1778088649964_m2.jpg
-rw-r--r-- 1 lukas staff 158980 6 May 20:30 1778088651015_m1.jpg
-rw-r--r-- 1 lukas staff 158729 6 May 20:30 1778088656510_m1.jpg
-rw-r--r-- 1 lukas staff 251895 6 May 20:30 1778088657626_m2.jpg
-rw-r--r-- 1 lukas staff 159037 6 May 20:31 1778088660760_m1.jpg
-rw-r--r-- 1 lukas staff 170173 6 May 20:31 1778088661602_m2.jpg
-rw-r--r-- 1 lukas staff 159039 6 May 20:31 1778088664406_m1.jpg
-rw-r--r-- 1 lukas staff 168123 6 May 20:31 1778088664871_m2.jpg
-rw-r--r-- 1 lukas staff 161993 6 May 20:31 1778088668555_m2.jpg
-rw-r--r-- 1 lukas staff 163729 6 May 20:31 1778088671392_m2.jpg
-rw-r--r-- 1 lukas staff 155859 6 May 20:31 1778088683595_m1.jpg
-rw-r--r-- 1 lukas staff 135122 6 May 20:31 1778088685154_m2.jpg
-rw-r--r-- 1 lukas staff 140146 6 May 20:31 1778088695364_m2.jpg
-rw-r--r-- 1 lukas staff 155883 6 May 20:31 1778088696205_m1.jpg
-rw-r--r-- 1 lukas staff 166491 6 May 20:31 1778088699449_m2.jpg
-rw-r--r-- 1 lukas staff 155839 6 May 20:31 1778088699457_m1.jpg
-rw-r--r-- 1 lukas staff 162622 6 May 20:31 1778088702773_m2.jpg
-rw-r--r-- 1 lukas staff 189289 6 May 20:31 1778088703280_m1.jpg
-rw-r--r-- 1 lukas staff 227256 6 May 20:32 1778088745343_m1.jpg
-rw-r--r-- 1 lukas staff 162471 6 May 20:32 1778088745907_m2.jpg
-rw-r--r-- 1 lukas staff 159690 6 May 20:32 1778088767221_m1.jpg
-rw-r--r-- 1 lukas staff 228402 6 May 20:34 1778088862349_m1.jpg
-rw-r--r-- 1 lukas staff 162494 6 May 20:34 1778088862922_m2.jpg
-rw-r--r-- 1 lukas staff 228391 6 May 20:34 1778088895443_m1.jpg
-rw-r--r-- 1 lukas staff 162695 6 May 20:34 1778088897069_m2.jpg
-rw-r--r-- 1 lukas staff 228420 6 May 20:35 1778088926328_m1.jpg
-rw-r--r-- 1 lukas staff 162684 6 May 20:35 1778088927793_m2.jpg
-rw-r--r-- 1 lukas staff 228407 6 May 20:35 1778088957089_m1.jpg
-rw-r--r-- 1 lukas staff 162545 6 May 20:35 1778088958635_m2.jpg
-rw-r--r-- 1 lukas staff 228407 6 May 20:36 1778088987860_m1.jpg
-rw-r--r-- 1 lukas staff 162483 6 May 20:36 1778088989374_m2.jpg
-rw-r--r-- 1 lukas staff 228420 6 May 20:36 1778089018527_m1.jpg
-rw-r--r-- 1 lukas staff 162536 6 May 20:37 1778089020270_m2.jpg
-rw-r--r-- 1 lukas staff 228372 6 May 20:37 1778089049194_m1.jpg
-rw-r--r-- 1 lukas staff 162683 6 May 20:37 1778089050974_m2.jpg
-rw-r--r-- 1 lukas staff 228412 6 May 20:38 1778089079866_m1.jpg
-rw-r--r-- 1 lukas staff 162494 6 May 20:38 1778089081721_m2.jpg
-rw-r--r-- 1 lukas staff 228380 6 May 20:38 1778089110848_m1.jpg
-rw-r--r-- 1 lukas staff 162606 6 May 20:38 1778089112768_m2.jpg
-rw-r--r-- 1 lukas staff 228380 6 May 20:39 1778089141520_m1.jpg
-rw-r--r-- 1 lukas staff 162611 6 May 20:39 1778089143498_m2.jpg
-rw-r--r-- 1 lukas staff 228353 6 May 20:39 1778089172629_m1.jpg
-rw-r--r-- 1 lukas staff 162480 6 May 20:39 1778089174323_m2.jpg
-rw-r--r-- 1 lukas staff 228332 6 May 20:40 1778089203288_m1.jpg
-rw-r--r-- 1 lukas staff 162502 6 May 20:40 1778089205370_m2.jpg
-rw-r--r-- 1 lukas staff 228372 6 May 20:40 1778089234520_m1.jpg
-rw-r--r-- 1 lukas staff 162571 6 May 20:40 1778089236266_m2.jpg
-rw-r--r-- 1 lukas staff 228416 6 May 20:41 1778089265485_m1.jpg
-rw-r--r-- 1 lukas staff 162636 6 May 20:41 1778089267383_m2.jpg
-rw-r--r-- 1 lukas staff 228362 6 May 20:41 1778089296562_m1.jpg
-rw-r--r-- 1 lukas staff 162564 6 May 20:41 1778089298295_m2.jpg
-rw-r--r-- 1 lukas staff 228392 6 May 20:42 1778089327270_m1.jpg
-rw-r--r-- 1 lukas staff 162605 6 May 20:42 1778089329081_m2.jpg
-rw-r--r-- 1 lukas staff 230328 6 May 20:42 1778089358286_m1.jpg
-rw-r--r-- 1 lukas staff 162589 6 May 20:42 1778089360293_m2.jpg
-rw-r--r-- 1 lukas staff 1038222 6 May 20:40 compact_monitor_1_1778089220643.mp4
-rw-r--r-- 1 lukas staff 327159 6 May 20:40 compact_monitor_2_1778089221749.mp4
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-05-06 $
DOCKER
Close Tab
DEV (docker)
Close Tab
APP (-zsh)
Close Tab
-zsh
Close Tab
screenpipe"
Close Tab
-zsh
Close Tab
⌥⌘1
-zsh...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
92
|
7
|
6
|
2026-05-06T17:43:23.611542+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778089403611_m1.jpg...
|
QuickTime Player
|
compact_monitor_1_1778089220643.mp4
|
True
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
rewind
play/pause
fast forward
More Controls
toggl rewind
play/pause
fast forward
More Controls
toggle full screen
show external playback menu
show external playback menu
show media selection menu
toggle picture-in-picture playback
show action menu
share
show chapter menu
zoom
zoom
playback speed
00:36
toggle elapsed time, timecode and framecount
02:10
toggle duration and remaining time
document actions
compact_monitor_1_1778089220643.mp4...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"rewind","depth":1,"bounds":{"left":0.47916666,"top":0.7861111,"width":0.017361112,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXCheckBox","text":"play/pause","depth":1,"bounds":{"left":0.50381947,"top":0.77666664,"width":0.02013889,"height":0.037777778},"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":true},{"role":"AXButton","text":"fast forward","depth":1,"bounds":{"left":0.5315972,"top":0.7861111,"width":0.017361112,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"More Controls","depth":1,"bounds":{"left":0.653125,"top":0.78555554,"width":0.0125,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXCheckBox","text":"toggle full screen","depth":1,"bounds":{"left":0.590625,"top":0.7916667,"width":0.013888889,"height":0.022222223},"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"show external playback menu","depth":1,"bounds":{"left":0.590625,"top":0.78444445,"width":0.013888889,"height":0.022222223},"on_screen":true,"role_description":"button","is_focused":false},{"role":"AXButton","text":"show external playback menu","depth":2,"bounds":{"left":0.590625,"top":0.78444445,"width":0.013888889,"height":0.022222223},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"show media selection menu","depth":1,"bounds":{"left":0.590625,"top":0.7916667,"width":0.015277778,"height":0.022222223},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"toggle picture-in-picture playback","depth":1,"bounds":{"left":0.6170139,"top":0.7838889,"width":0.017361112,"height":0.022222223},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"show action menu","depth":1,"bounds":{"left":0.590625,"top":0.7911111,"width":0.014583333,"height":0.023333333},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"share","depth":1,"bounds":{"left":0.646875,"top":0.78055555,"width":0.013541667,"height":0.025555555},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"show chapter menu","depth":1,"bounds":{"left":0.590625,"top":0.79444444,"width":0.014583333,"height":0.016666668},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXCheckBox","text":"zoom","depth":1,"bounds":{"left":0.590625,"top":0.78944445,"width":0.013888889,"height":0.026666667},"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXCheckBox","text":"zoom","depth":1,"bounds":{"left":0.590625,"top":0.7922222,"width":0.017361112,"height":0.02111111},"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"playback speed","depth":1,"bounds":{"left":0.590625,"top":0.7922222,"width":0.013194445,"height":0.02111111},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXStaticText","text":"00:36","depth":1,"bounds":{"left":0.36215279,"top":0.82277775,"width":0.02638889,"height":0.016666668},"on_screen":true,"role_description":"text"},{"role":"AXCheckBox","text":"toggle elapsed time, timecode and framecount","depth":1,"bounds":{"left":0.36354166,"top":0.82277775,"width":0.023611112,"height":0.016666668},"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXStaticText","text":"02:10","depth":1,"bounds":{"left":0.6340278,"top":0.82277775,"width":0.031597223,"height":0.016666668},"on_screen":true,"role_description":"text"},{"role":"AXCheckBox","text":"toggle duration and remaining time","depth":1,"bounds":{"left":0.6354167,"top":0.82277775,"width":0.028819444,"height":0.016666668},"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXMenuButton","text":"document actions","depth":1,"bounds":{"left":0.6173611,"top":0.033333335,"width":0.0069444445,"height":0.017777778},"on_screen":true,"role_description":"menu button","is_enabled":false,"is_focused":false},{"role":"AXStaticText","text":"compact_monitor_1_1778089220643.mp4","depth":1,"bounds":{"left":0.42222223,"top":0.033333335,"width":0.19513889,"height":0.017777778},"on_screen":true,"role_description":"text"}]...
|
8399486893233851489
|
7091812361059449462
|
visual_change
|
hybrid
|
NULL
|
rewind
play/pause
fast forward
More Controls
toggl rewind
play/pause
fast forward
More Controls
toggle full screen
show external playback menu
show external playback menu
show media selection menu
toggle picture-in-picture playback
show action menu
share
show chapter menu
zoom
zoom
playback speed
00:36
toggle elapsed time, timecode and framecount
02:10
toggle duration and remaining time
document actions
compact_monitor_1_1778089220643.mp4
QuickTime PlayerFileEditViewWindowHelpAcompact_monitor_1_1778089220643.mp4 v-zsh-rw--ГW--rw-r--r--rw--rw-r--r---rw-I-rw-r--r--rw-i-rw-r--r---rw-!-rw-r--r--DOCKERDEV (docker)APP (-zsh)X3lukasstaff20842417Apr 21:06lukasstaffscreenpipe.2026-04-17.0.10g6198318Apr 14:45screenpipe.2026-04-18.0.1og1lukasstaff35980020Apr18:52lukasstaff68367121Apr20:18screenpipe.2026-04-20.0.10gscreenpipe.2026-04-21.0.10g1 lukasstaff28476322Apr19:101lukasstaff1763862314:01screenpipe.2026-04-22.0.logstaffAprscreenpipe.2026-04-23.0.10g-rw-i-rw-r--r--lukas276189lukas22:35-rw-I-rw-r--r--staff24Aprscreenpipe.2026-04-24.0.1og6879425Apr19:40-rw--rw-r--r--1 lukasstaff7554326 Apr22:56screenpipe.2026-04-25.0.10gscreenpipe.2026-04-26.0.10g-rw--rw-r--r--1 lukasstaff60781127Apr20:42-ГW--rw-r--r--1lukasstaff39609428Aprscreenpipe.2026-04-27.0.1og22:23-rw-i-rwxr-xr-xe1 lukasstaff1499425screenpipe.2026-04-28.0.10gApr 18:50-rw-1-rw-r--r--®1 lukasstaffscreenpipe_sync.sh348236 May 18:58sync. log-rw-iukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh-rw-#!/bin/bash-rw-screenpipe_sync.sh-rw-Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).-rw-I# Also copies the day's video/frame data folder to the NAS.-rw--rw--ГW--rw--rw-iUsage:./screenpipe_sync.sh/screenpipe_sync.sh 2026-04-15./screenpipe_sync.sh today# syncs yesterday (default)# syncs a specific date#syncs today sofar-rw-i-rw-!Cron example (runs at 3am daily):0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh » /Users/lukas/.screenpipe/sync.log 2>&1-rw-iset -euo pipefail-rw--rw-CONFIG-rw--ГW-DB_SRC-"S(SCREENPIPE_DB: -SHOME/.screenpipe/db.sqlite}"NAS_MOUNT-"S-(NAS_MOUNT: -/Volumes/screenpipe}*-rw-i-rw-INAS_DB-"SNAS_MOUNT/archive.db"NAS_DATA-"SNAS_MOUNT/data"-rw-i-rw-iLOG_FILE="SHOME/.screenpipe/sync.log"-rW--rw-#HELPERS-rW-| SCRIPT_START-S(date +%s)-rw--rw-!logO {-ГW-local msg="[S(date '+%Y-%m-%d %H:XM:%5')] 5**-rw-iecho "Smsg"I tee -a "SLOG_FILE"luka:}Luka00:36X4screenpipe*X597% <4Wed 6 May 20:43:25TX1-zshX602:10...
|
90
|
/Users/lukas/.screenpipe/data/data/2026-05-06/comp /Users/lukas/.screenpipe/data/data/2026-05-06/compact_monitor_1_1778089220643.mp4...
|
NULL
|
NULL
|
|
93
|
8
|
6
|
2026-05-06T17:43:27.180009+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778089407180_m2.jpg...
|
QuickTime Player
|
compact_monitor_1_1778089220643.mp4
|
True
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
rewind
play/pause
fast forward
More Controls
toggl rewind
play/pause
fast forward
More Controls
toggle full screen
show external playback menu
show external playback menu
show media selection menu
toggle picture-in-picture playback
show action menu
share
show chapter menu
zoom
zoom
playback speed
00:02
toggle elapsed time, timecode and framecount
02:10
toggle duration and remaining time
document actions
compact_monitor_1_1778089220643.mp4...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"rewind","depth":1,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXCheckBox","text":"play/pause","depth":1,"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":true},{"role":"AXButton","text":"fast forward","depth":1,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"More Controls","depth":1,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXCheckBox","text":"toggle full screen","depth":1,"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"show external playback menu","depth":1,"on_screen":true,"role_description":"button","is_focused":false},{"role":"AXButton","text":"show external playback menu","depth":2,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"show media selection menu","depth":1,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"toggle picture-in-picture playback","depth":1,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"show action menu","depth":1,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"share","depth":1,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"show chapter menu","depth":1,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXCheckBox","text":"zoom","depth":1,"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXCheckBox","text":"zoom","depth":1,"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"playback speed","depth":1,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXStaticText","text":"00:02","depth":1,"on_screen":true,"role_description":"text"},{"role":"AXCheckBox","text":"toggle elapsed time, timecode and framecount","depth":1,"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXStaticText","text":"02:10","depth":1,"on_screen":true,"role_description":"text"},{"role":"AXCheckBox","text":"toggle duration and remaining time","depth":1,"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXMenuButton","text":"document actions","depth":1,"bounds":{"left":0.56582445,"top":1.0,"width":0.0033244682,"height":-0.02394259},"on_screen":true,"role_description":"menu button","is_enabled":false,"is_focused":false},{"role":"AXStaticText","text":"compact_monitor_1_1778089220643.mp4","depth":1,"bounds":{"left":0.47240692,"top":1.0,"width":0.093417555,"height":-0.02394259},"on_screen":true,"role_description":"text"}]...
|
3753959356252715853
|
7127840162786847350
|
click
|
hybrid
|
NULL
|
rewind
play/pause
fast forward
More Controls
toggl rewind
play/pause
fast forward
More Controls
toggle full screen
show external playback menu
show external playback menu
show media selection menu
toggle picture-in-picture playback
show action menu
share
show chapter menu
zoom
zoom
playback speed
00:02
toggle elapsed time, timecode and framecount
02:10
toggle duration and remaining time
document actions
compact_monitor_1_1778089220643.mp4
DMSAC.MILVAll 4DMsloastApp[no preview availablel11 | 10:00 AMIMonday. May 4th-7 Jira Cloud@ 15 Monday@Nikolay Ivanov transitioned aBug you are watching from Code...Wednesday, April 29thAneliva AngelovaWednesdayStoyan Tanev6 DMWednesdavнаша стоананTuesday. April 28th?1 Stefka StoyanovaApr 28thтия тикети е добре да влезнат вдругия спринт ли? сложете някакви...Ves@ Thread in DM: исках да те...смени го в Circle Cl env на новиятокен който си напларилApr 28thStefka Stoyano… Replied Apr 28thAOMIпnuaтна oтлуска СStetka Stovanova and …... Aor 28thl•• 0‹→ сN& Adelina Petrova "Pull requests • screenpipe/screenpipe • GitHubMessagesLo Add canvasUr Files# Hostinger login | Sign in to Hostinger accountне, само стр се тракватLogin - Nginx Proxy ManagerLukas Kovalik IN 1:15 PM* Screenpipe - ArchiveAdelina Petrova "T 1:42 PMpagesLukas Kovalik "T 1:43 PMЯСНО@ SQLite Web: archive.db©SQLite Web: db.sqliteAdelina Petrova 5:06 PMда не ои проолема да е заради това кю: QUEUE,DELAYANew TabLukas Kovalik * 5:06 PMscreenpipe/,claude/skills at main • screenpipe/screenpза това искам да дооавя логовеAdelina Petrova 5:07 PMUAVDA MO CTAUG SUA rA MaVUOLI?има ли риск за нещоLukas Kovalik " 5:08 PMвсишност нама опашка тукаAdelina Petrova " 5:12 PM• сега, няма ли ла сложи евента в това кю и ла цака изпьл.Lukas Kovalik *T 5:21 PMла, ше оставя detault изпь лнениеLukas Kovalik 1K 5-26 PMпо поинцип го направих като nudge-created че те не са о!•и глелам че и този event няма никойAdelina Petrova" 5:33PMспорел мен пробвай без това кюLukas Kovalik * 5:33 PMhttps://run.userpilot.io/events/tracked_event/10run.userpilot.ioUserpilotUserpilot helos product teams deliver personalized in-appgrowth metrics at every stage of the user lournev.не е това обаче, гледам че всички си минават през сьщиAdelina Petrova * 5:40 PMами эко можеш сложи тогава лог да го видимAdelina Petrova has paused their notificationsMessage Adelina Petrova " VacationingAaO Not Secure http:/[IP_ADDRESS]:8768/audio_transcriptions_fts_idx/audio_tagsaualo transcriptionsaudio_transcriptions_fts (v)audio_transcriptions_audio_transcriptions_.audio_transcriptions_...elementselements_fts (v)elements_fts_configelements_fts_dataelements_fts_idxframesframes_fts (")frames_fts_configframes_fts_dataframes_fts_idxmeetingsmemoriesmemories_fts (v)memories_fts_configmemories_fts_datamemories_fts_idxocr_textpipe_executionspipe_scheduler_statesecretsspeaker_embeddingsspeakerssqlite_sequencesqlite_statlsalite_statatagsui_eventsui_events_fts (v)ui_events_fts_configui_events_fts_dataui_events_fts_idxvideo_chunksvision_tagsCREATE TABLE 'audio_transcriptions_fts_idx' (segid,term,PRIMARY KEY(segid, term)ColumnsColumnData typesegidpgnoIndexesNameColumnsSQLite database browser v0.7.2, powered by Flask and Peewee. © 2026 Charles LeiferToggle helper tablesAllow nullUniquePrimary keySOLW6MaY 20:43:27OSOEOEActionsread-onlyread-onlyread-onlyDrop?...
|
91
|
/Users/lukas/.screenpipe/data/data/2026-05-06/comp /Users/lukas/.screenpipe/data/data/2026-05-06/compact_monitor_1_1778089220643.mp4...
|
NULL
|
NULL
|
|
94
|
7
|
7
|
2026-05-06T17:43:29.020374+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778089409020_m1.jpg...
|
QuickTime Player
|
compact_monitor_1_1778089220643.mp4
|
True
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
rewind
play/pause
fast forward
More Controls
toggl rewind
play/pause
fast forward
More Controls
toggle full screen
show external playback menu
show external playback menu
show media selection menu
toggle picture-in-picture playback
show action menu
share
show chapter menu
zoom
zoom
playback speed
00:00
toggle elapsed time, timecode and framecount
02:10
toggle duration and remaining time
document actions
compact_monitor_1_1778089220643.mp4...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"rewind","depth":1,"bounds":{"left":0.47916666,"top":0.7861111,"width":0.017361112,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXCheckBox","text":"play/pause","depth":1,"bounds":{"left":0.50381947,"top":0.77666664,"width":0.02013889,"height":0.037777778},"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":true},{"role":"AXButton","text":"fast forward","depth":1,"bounds":{"left":0.5315972,"top":0.7861111,"width":0.017361112,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"More Controls","depth":1,"bounds":{"left":0.653125,"top":0.78555554,"width":0.0125,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXCheckBox","text":"toggle full screen","depth":1,"bounds":{"left":0.590625,"top":0.7916667,"width":0.013888889,"height":0.022222223},"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"show external playback menu","depth":1,"bounds":{"left":0.590625,"top":0.78444445,"width":0.013888889,"height":0.022222223},"on_screen":true,"role_description":"button","is_focused":false},{"role":"AXButton","text":"show external playback menu","depth":2,"bounds":{"left":0.590625,"top":0.78444445,"width":0.013888889,"height":0.022222223},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"show media selection menu","depth":1,"bounds":{"left":0.590625,"top":0.7916667,"width":0.015277778,"height":0.022222223},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"toggle picture-in-picture playback","depth":1,"bounds":{"left":0.6170139,"top":0.7838889,"width":0.017361112,"height":0.022222223},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"show action menu","depth":1,"bounds":{"left":0.590625,"top":0.7911111,"width":0.014583333,"height":0.023333333},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"share","depth":1,"bounds":{"left":0.646875,"top":0.78055555,"width":0.013541667,"height":0.025555555},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"show chapter menu","depth":1,"bounds":{"left":0.590625,"top":0.79444444,"width":0.014583333,"height":0.016666668},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXCheckBox","text":"zoom","depth":1,"bounds":{"left":0.590625,"top":0.78944445,"width":0.013888889,"height":0.026666667},"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXCheckBox","text":"zoom","depth":1,"bounds":{"left":0.590625,"top":0.7922222,"width":0.017361112,"height":0.02111111},"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"playback speed","depth":1,"bounds":{"left":0.590625,"top":0.7922222,"width":0.013194445,"height":0.02111111},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXStaticText","text":"00:00","depth":1,"bounds":{"left":0.36215279,"top":0.82277775,"width":0.02638889,"height":0.016666668},"on_screen":true,"role_description":"text"},{"role":"AXCheckBox","text":"toggle elapsed time, timecode and framecount","depth":1,"bounds":{"left":0.36354166,"top":0.82277775,"width":0.023611112,"height":0.016666668},"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXStaticText","text":"02:10","depth":1,"bounds":{"left":0.6340278,"top":0.82277775,"width":0.031597223,"height":0.016666668},"on_screen":true,"role_description":"text"},{"role":"AXCheckBox","text":"toggle duration and remaining time","depth":1,"bounds":{"left":0.6354167,"top":0.82277775,"width":0.028819444,"height":0.016666668},"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXMenuButton","text":"document actions","depth":1,"bounds":{"left":0.6173611,"top":0.033333335,"width":0.0069444445,"height":0.017777778},"on_screen":true,"role_description":"menu button","is_enabled":false,"is_focused":false},{"role":"AXStaticText","text":"compact_monitor_1_1778089220643.mp4","depth":1,"bounds":{"left":0.42222223,"top":0.033333335,"width":0.19513889,"height":0.017777778},"on_screen":true,"role_description":"text"}]...
|
-5321610022062171554
|
7127834596442118774
|
visual_change
|
hybrid
|
NULL
|
rewind
play/pause
fast forward
More Controls
toggl rewind
play/pause
fast forward
More Controls
toggle full screen
show external playback menu
show external playback menu
show media selection menu
toggle picture-in-picture playback
show action menu
share
show chapter menu
zoom
zoom
playback speed
00:00
toggle elapsed time, timecode and framecount
02:10
toggle duration and remaining time
document actions
compact_monitor_1_1778089220643.mp4
QuickTime PlayerFileEditViewWindowHelpA97% <4Wed 6 May 20:43:29compact_monitor_1_1778089220643.mp4 vscreenpipe"1X1-rw--ГW--rw-i-rw-1-rw-i-rw-!-rW-I-rw-i-rw-i-rw--rw-l-rW--rw-!-rw-1DOCKERapi authencrypt secretsretention daysretention modeDEV (docker)X2APP (-zsh)X3-zshX4screenpipe*X5-zshX6enableddisabled7Q- you‹ › xmedia-only (keep transcripts)languagesall languagesmonitorsid: 1id: 2audio devicesMacBook Pro Microphone (input)System Audio (output)-rw--rw--rw-are using local processing. alldata stayscomputer.-rw-1-rw-i-rw-lwarning: telemetry is enabled.only error-leveldata will be sent.to disable, use the --disable-telemetry flag.-rW--rw-check latest changes here: https://github.com/screenpipe/screenpipe/releases-rw-I2026-05-06T20:27:34.638384ZINFOscreenpipe:starting UI event capture2026-05-06T20:27:34.6376792INFO-rw-iscreenpipe_core::pipes: pipe scheduler started (generation 2)2026-05-06T20:27:34.649154ZINFOscreenpipe_engine::power::manager:-rw-t2026-05-06T20:27:34.6527942WARN-ГW-screenpipe: piinitial power profile: Performance (on_ac=true, battery=Some(94))install failed: bun not found - install from https://bun.sh2026-05-06T20:27:34.655839ZINFO-rw-iscreenpipe_engine::ui_recorder: Starting UI event capture2026-05-06T20:27:34.6738772-rw-IINFO2026-05-06T20:27:34673910ZINFOscreenpipe_engine::ui_recorder: UI recording session started: 54869993-7b4b-491f-b717-2a583517f9c5screenpipe_engine::calendar_speaker_id: speaker identification: started (user_name=<not set>)-rw-2026-05-06T20:27:346740572-rw-iINFOscreenpipe_engine::hot_frame_cache: hot_frame_cache: warming from DB (2026-05-05 17:27:34.674056 UTC to 2026-05-06 17:27:34.674056 UTC)-ГW-2026-05-06T20:27:34.674892ZINFOscreenpipe_engine::meeting_detector: meeting v2: detection loop started (base_interval-5s, profiles=12)2026-05-06T20:27:34.6757882INFO2026-05-06T20:27:34686546ZINFOscreenpipe_engine::hot_frame_cache: hot_frame_cache: warmed with 0 frame entries, coverage from 2026-05-05 17:27:34.674056 UTC-rw-i2026-05-06T20:27:34691371ZINFOscreenpipe_engine::server:Server listening on [IP_ADDRESS]:3030-rw-1screenpipe_connect: :mdns:mdns: advertisina screenpipe on port 30302026-05-06T20:27:36-rw-!:270608ZINFOscreenpipe_engine::viston_1440x900)2026-05-06T20:27:36.270669ZINFOscreenpipe_engine::viston-ГW-2026-05-06120:27:36.2707142INFO-rw-iscreenpipe_engine::event_d00:002026-05-06T20:27:36.932583ZINFOscreenpipe_engine::viston_-rw-| 2026-05-06T20:27:36.932852ZINFOscreenpipe_engine::vision_manager::managf: Starting event-driven capture for monitor 2 (device: monitor_2)- rw-i2026-05-06T20:27:36.932882Zscreenpipe_engine::vision_manager::manager: VisionManager started with 2/2 monitor(s)-rw-l2026-05-06T20:27:36.932899Zscreenpipe_engine::vision_manager::monitor_watcher: Starting monitor watcher (event-driven via CGDisplayRegisterReconfigurationCallback, 60s bac-ГW-kstop poll)-rw-!2026-05-06T20:27:36.932901Zluka: 2026-05-06T20:27:39.158281ZINFOscreenpipe_engine::event_driven_capture: event-driven capture started for monitor 2 (device: monitor_2)INFO sck_rs::stream_manager: persistent SCK stream started for display 1 (1440x900, 2fps, 3 excluded)luka...
|
NULL
|
/Users/lukas/.screenpipe/data/data/2026-05-06/comp /Users/lukas/.screenpipe/data/data/2026-05-06/compact_monitor_1_1778089220643.mp4...
|
NULL
|
NULL
|
|
95
|
8
|
7
|
2026-05-06T17:43:29.145346+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778089409145_m2.jpg...
|
QuickTime Player
|
compact_monitor_1_1778089220643.mp4
|
True
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
rewind
play/pause
fast forward
More Controls
toggl rewind
play/pause
fast forward
More Controls
toggle full screen
show external playback menu
show external playback menu
show media selection menu
toggle picture-in-picture playback
show action menu
share
show chapter menu
zoom
zoom
playback speed
00:00
toggle elapsed time, timecode and framecount
02:10
toggle duration and remaining time
document actions
compact_monitor_1_1778089220643.mp4...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"rewind","depth":1,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXCheckBox","text":"play/pause","depth":1,"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":true},{"role":"AXButton","text":"fast forward","depth":1,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"More Controls","depth":1,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXCheckBox","text":"toggle full screen","depth":1,"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"show external playback menu","depth":1,"on_screen":true,"role_description":"button","is_focused":false},{"role":"AXButton","text":"show external playback menu","depth":2,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"show media selection menu","depth":1,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"toggle picture-in-picture playback","depth":1,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"show action menu","depth":1,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"share","depth":1,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"show chapter menu","depth":1,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXCheckBox","text":"zoom","depth":1,"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXCheckBox","text":"zoom","depth":1,"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"playback speed","depth":1,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXStaticText","text":"00:00","depth":1,"on_screen":true,"role_description":"text"},{"role":"AXCheckBox","text":"toggle elapsed time, timecode and framecount","depth":1,"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXStaticText","text":"02:10","depth":1,"on_screen":true,"role_description":"text"},{"role":"AXCheckBox","text":"toggle duration and remaining time","depth":1,"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXMenuButton","text":"document actions","depth":1,"bounds":{"left":0.56582445,"top":1.0,"width":0.0033244682,"height":-0.02394259},"on_screen":true,"role_description":"menu button","is_enabled":false,"is_focused":false},{"role":"AXStaticText","text":"compact_monitor_1_1778089220643.mp4","depth":1,"bounds":{"left":0.47240692,"top":1.0,"width":0.093417555,"height":-0.02394259},"on_screen":true,"role_description":"text"}]...
|
-5321610022062171554
|
7127834596442118774
|
click
|
hybrid
|
NULL
|
rewind
play/pause
fast forward
More Controls
toggl rewind
play/pause
fast forward
More Controls
toggle full screen
show external playback menu
show external playback menu
show media selection menu
toggle picture-in-picture playback
show action menu
share
show chapter menu
zoom
zoom
playback speed
00:00
toggle elapsed time, timecode and framecount
02:10
toggle duration and remaining time
document actions
compact_monitor_1_1778089220643.mp4
DMSAC.MILVAll 4DMsloastApp[no preview availablel11 | 10:00 AMIMonday. May 4th-7 Jira Cloud@ 15 Monday@Nikolay Ivanov transitioned aBug you are watching from Code...Wednesday, April 29thAneliva AngelovaWednesdayStoyan Tanev6 DMWednesdavнаша стоананTuesday. April 28th?1 Stefka StoyanovaApr 28thтия тикети е добре да влезнат вдругия спринт ли? сложете някакви...Ves@ Thread in DM: исках да те...смени го в Circle Cl env на новиятокен който си напларилApr 28thStefka Stoyano… Replied Apr 28thAOMIпnuaтна oтлуска СStetka Stovanova and …... Aor 28thl•• 0‹→ сN& Adelina Petrova "Pull requests • screenpipe/screenpipe • GitHubMessagesLo Add canvasUr Files# Hostinger login | Sign in to Hostinger accountне, само стр се тракватLogin - Nginx Proxy ManagerLukas Kovalik IN 1:15 PM* Screenpipe - ArchiveAdelina Petrova "T 1:42 PMpagesLukas Kovalik "T 1:43 PMЯСНО@ SQLite Web: archive.db©SQLite Web: db.sqliteAdelina Petrova 5:06 PMда не ои проолема да е заради това кю: QUEUE,DELAYANew TabLukas Kovalik * 5:06 PMscreenpipe/,claude/skills at main • screenpipe/screenpза това искам да дооавя логовеAdelina Petrova 5:07 PMUAVDA MO CTAUG SUA rA MaVUOLI?има ли риск за нещоLukas Kovalik " 5:08 PMвсишност нама опашка тукаAdelina Petrova " 5:12 PM• сега, няма ли ла сложи евента в това кю и ла цака изпьл.Lukas Kovalik *T 5:21 PMла, ше оставя detault изпь лнениеLukas Kovalik 1K 5-26 PMпо поинцип го направих като nudge-created че те не са о!•и глелам че и този event няма никойAdelina Petrova" 5:33PMспорел мен пробвай без това кюLukas Kovalik * 5:33 PMhttps://run.userpilot.io/events/tracked_event/10run.userpilot.ioUserpilotUserpilot helos product teams deliver personalized in-appgrowth metrics at every stage of the user lournev.не е това обаче, гледам че всички си минават през сьщиAdelina Petrova * 5:40 PMами эко можеш сложи тогава лог да го видимAdelina Petrova has paused their notificationsMessage Adelina Petrova " VacationingAaO Not Secure http:/[IP_ADDRESS]:8768/audio_transcriptions_fts_idx/audio_tagsaualo transcriptionsaudio_transcriptions_fts (v)audio_transcriptions_audio_transcriptions_.audio_transcriptions_...elementselements_fts (v)elements_fts_configelements_fts_dataelements_fts_idxframesframes_fts (")frames_fts_configframes_fts_dataframes_fts_idxmeetingsmemoriesmemories_fts (v)memories_fts_configmemories_fts_datamemories_fts_idxocr_textpipe_executionspipe_scheduler_statesecretsspeaker_embeddingsspeakerssqlite_sequencesqlite_statlsalite_statatagsui_eventsui_events_fts (v)ui_events_fts_configui_events_fts_dataui_events_fts_idxvideo_chunksvision_tagsCREATE TABLE 'audio_transcriptions_fts_idx' (segid,term,PRIMARY KEY(segid, term)ColumnsColumnData typesegidpgnoIndexesNameColumnsSQLite database browser v0.7.2, powered by Flask and Peewee. © 2026 Charles LeiferToggle helper tablesAllow nullUniquePrimary keySOLW6MaY 20:43:30Actionsread-onlyread-onlyread-onlyDrop?...
|
NULL
|
/Users/lukas/.screenpipe/data/data/2026-05-06/comp /Users/lukas/.screenpipe/data/data/2026-05-06/compact_monitor_1_1778089220643.mp4...
|
NULL
|
NULL
|
|
96
|
7
|
8
|
2026-05-06T17:43:31.219716+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778089411219_m1.jpg...
|
QuickTime Player
|
compact_monitor_1_1778089220643.mp4
|
True
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
rewind
play/pause
fast forward
More Controls
toggl rewind
play/pause
fast forward
More Controls
toggle full screen
show external playback menu
show external playback menu
show media selection menu
toggle picture-in-picture playback
show action menu
share
show chapter menu
zoom
zoom
playback speed
00:02
toggle elapsed time, timecode and framecount
02:10
toggle duration and remaining time
document actions
compact_monitor_1_1778089220643.mp4...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"rewind","depth":1,"bounds":{"left":0.47916666,"top":0.7861111,"width":0.017361112,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXCheckBox","text":"play/pause","depth":1,"bounds":{"left":0.50381947,"top":0.77666664,"width":0.02013889,"height":0.037777778},"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":true},{"role":"AXButton","text":"fast forward","depth":1,"bounds":{"left":0.5315972,"top":0.7861111,"width":0.017361112,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"More Controls","depth":1,"bounds":{"left":0.653125,"top":0.78555554,"width":0.0125,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXCheckBox","text":"toggle full screen","depth":1,"bounds":{"left":0.590625,"top":0.7916667,"width":0.013888889,"height":0.022222223},"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"show external playback menu","depth":1,"bounds":{"left":0.590625,"top":0.78444445,"width":0.013888889,"height":0.022222223},"on_screen":true,"role_description":"button","is_focused":false},{"role":"AXButton","text":"show external playback menu","depth":2,"bounds":{"left":0.590625,"top":0.78444445,"width":0.013888889,"height":0.022222223},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"show media selection menu","depth":1,"bounds":{"left":0.590625,"top":0.7916667,"width":0.015277778,"height":0.022222223},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"toggle picture-in-picture playback","depth":1,"bounds":{"left":0.6170139,"top":0.7838889,"width":0.017361112,"height":0.022222223},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"show action menu","depth":1,"bounds":{"left":0.590625,"top":0.7911111,"width":0.014583333,"height":0.023333333},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"share","depth":1,"bounds":{"left":0.646875,"top":0.78055555,"width":0.013541667,"height":0.025555555},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"show chapter menu","depth":1,"bounds":{"left":0.590625,"top":0.79444444,"width":0.014583333,"height":0.016666668},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXCheckBox","text":"zoom","depth":1,"bounds":{"left":0.590625,"top":0.78944445,"width":0.013888889,"height":0.026666667},"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXCheckBox","text":"zoom","depth":1,"bounds":{"left":0.590625,"top":0.7922222,"width":0.017361112,"height":0.02111111},"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"playback speed","depth":1,"bounds":{"left":0.590625,"top":0.7922222,"width":0.013194445,"height":0.02111111},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXStaticText","text":"00:02","depth":1,"bounds":{"left":0.36215279,"top":0.82277775,"width":0.02638889,"height":0.016666668},"on_screen":true,"role_description":"text"},{"role":"AXCheckBox","text":"toggle elapsed time, timecode and framecount","depth":1,"bounds":{"left":0.36354166,"top":0.82277775,"width":0.023611112,"height":0.016666668},"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXStaticText","text":"02:10","depth":1,"bounds":{"left":0.6340278,"top":0.82277775,"width":0.031597223,"height":0.016666668},"on_screen":true,"role_description":"text"},{"role":"AXCheckBox","text":"toggle duration and remaining time","depth":1,"bounds":{"left":0.6354167,"top":0.82277775,"width":0.028819444,"height":0.016666668},"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXMenuButton","text":"document actions","depth":1,"bounds":{"left":0.6173611,"top":0.033333335,"width":0.0069444445,"height":0.017777778},"on_screen":true,"role_description":"menu button","is_enabled":false,"is_focused":false},{"role":"AXStaticText","text":"compact_monitor_1_1778089220643.mp4","depth":1,"bounds":{"left":0.42222223,"top":0.033333335,"width":0.19513889,"height":0.017777778},"on_screen":true,"role_description":"text"}]...
|
3753959356252715853
|
7127840162786847350
|
click
|
hybrid
|
NULL
|
rewind
play/pause
fast forward
More Controls
toggl rewind
play/pause
fast forward
More Controls
toggle full screen
show external playback menu
show external playback menu
show media selection menu
toggle picture-in-picture playback
show action menu
share
show chapter menu
zoom
zoom
playback speed
00:02
toggle elapsed time, timecode and framecount
02:10
toggle duration and remaining time
document actions
compact_monitor_1_1778089220643.mp4
QuickTime PlayerFileEditViewWindowHelpG97% <4Wed 6 May 20:43:32compact_monitor_1_1778089220643.mp4 vscreenpipe"1X1-rw--ГW--rw-i-rw-1-rw-i-rw-!-rW-I-rw-i-rw-i-rw--rw-l-rW--rw-!-rw-1DOCKERapi authencrypt secretsretention daysretention modeDEV (docker)X2APP (-zsh)X3-zshX4screenpipe*X5-zshX6enableddisabled7Qu you‹ › xmedia-only (keep transcripts)languagesall languagesmonitorsid: 1id: 2audio devicesMacBook Pro Microphone (input)System Audio (output)-rw--rw--rw-are using local processing. alldata staysyoucomputer.-rw-1-rw-i-rw-lwarning: telemetry is enabled.only error-leveldata will be sent.to disable, use the --disable-telemetry flag.-rW--rw-check latest changes here: https://github.com/screenpipe/screenpipe/releases-rw-I2026-05-06T20:27:34.638384ZINFOscreenpipe:starting UI event capture2026-05-06T20:27:34.6376792INFO-rw-iscreenpipe_core::pipes: pipe scheduler started (generation 2)2026-05-06T20:27:34.649154ZINFOscreenpipe_engine::power::manager:-rw-t2026-05-06T20:27:34.6527942WARN-rW-screenpipe: piinitial power profile: Performance (on_ac=true, battery=Some(94))agentinstall failed: bun not found - install from https://bun.sh2026-05-06T20:27:34.655839ZINFO-rw-iscreenpipe_engine::ui_recorder: Starting UI event capture2026-05-06T20:27:34.6738772-rw-IINFO2026-05-06T20:27:34673910ZINFOscreenpipe_engine::ui_recorder: UI recording session started: 54869993-7b4b-491f-b717-2a583517f9c5screenpipe_engine::calendar_speaker_id: speaker identification: started (user_name=<not set>)-rw-2026-05-06T20:27:346740572-rw-iINFOscreenpipe_engine::hot_frame_cache: hot_frame_cache: warming from DB (2026-05-05 17:27:34.674056 UTC to 2026-05-06 17:27:34.674056 UTC)-ГW-2026-05-06T20:27:34.674892ZINFOscreenpipe_engine::meeting_detector: meeting v2: detection loop started (base_interval-5s, profiles=12)2026-05-06T20:27:34..6757882INFO2026-05-06T20:27:34686546ZINFOscreenpipe_engine::hot_frame_cache: hot_frame_cache: warmed with 0 frame entries, coverage from 2026-05-05 17:27:34.674056 UTC-rw-i2026-05-06T20:27:34691371ZINFOscreenpipe_engine::server:Server listening on [IP_ADDRESS]:3030-rw-1screenpipe_connect: :mdns:mdns: advertisina screenpipe onDort 30302026-05-06T20:27:36-rw-!:270608ZINFOscreenpipe_engine::viston_1440x900)2026-05-06T20:27:36.270669Zscreenpipe_engine::viston• 1 (device: monitor_1)-ГW-2026-05-06120:27:36.2707142-rw-iscreenpipe_engine::event_d(device: monitor_1)2026-05-06T20:27:36.932583Zscreenpipe_engine::viston_(3008x1253)-rw-| 2026-05-06T20:27:36.932852Zscreenpipe_engine::vision_manager::managf: Starting event-driven capture for monitor 2 (device: monitor_2)- rw-i2026-05-06T20:27:36.932882Zscreenpipe_engine::vision_manager::manager: VisionManager started with 2/2 monitor(s)-rw-l2026-05-06T20:27:36.932899Zscreenpipe_engine::vision_manager::monitor_watcher: Starting monitor watcher (event-driven via CGDisplayRegisterReconfigurationCallback, 60s bac-ГW-kstop poll)-rw-!2026-05-06T20:27:36.932901Zluka: 2026-05-06T20:27:39.158281ZINFOscreenpipe_engine::event_driven_capture: event-driven capture started for monitor 2 (device: monitor_2)INFO sck_rs::stream_manager: persistent SCK stream started for display 1 (1440x900, 2fps, 3 excluded)luka...
|
94
|
/Users/lukas/.screenpipe/data/data/2026-05-06/comp /Users/lukas/.screenpipe/data/data/2026-05-06/compact_monitor_1_1778089220643.mp4...
|
NULL
|
NULL
|
|
97
|
8
|
8
|
2026-05-06T17:43:31.737263+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778089411737_m2.jpg...
|
QuickTime Player
|
compact_monitor_1_1778089220643.mp4
|
True
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
rewind
play/pause
fast forward
More Controls
toggl rewind
play/pause
fast forward
More Controls
toggle full screen
show external playback menu
show external playback menu
show media selection menu
toggle picture-in-picture playback
show action menu
share
show chapter menu
zoom
zoom
playback speed
00:03
toggle elapsed time, timecode and framecount
02:10
toggle duration and remaining time
document actions
compact_monitor_1_1778089220643.mp4...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"rewind","depth":1,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXCheckBox","text":"play/pause","depth":1,"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":true},{"role":"AXButton","text":"fast forward","depth":1,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"More Controls","depth":1,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXCheckBox","text":"toggle full screen","depth":1,"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"show external playback menu","depth":1,"on_screen":true,"role_description":"button","is_focused":false},{"role":"AXButton","text":"show external playback menu","depth":2,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"show media selection menu","depth":1,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"toggle picture-in-picture playback","depth":1,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"show action menu","depth":1,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"share","depth":1,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"show chapter menu","depth":1,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXCheckBox","text":"zoom","depth":1,"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXCheckBox","text":"zoom","depth":1,"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"playback speed","depth":1,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXStaticText","text":"00:03","depth":1,"on_screen":true,"role_description":"text"},{"role":"AXCheckBox","text":"toggle elapsed time, timecode and framecount","depth":1,"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXStaticText","text":"02:10","depth":1,"on_screen":true,"role_description":"text"},{"role":"AXCheckBox","text":"toggle duration and remaining time","depth":1,"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXMenuButton","text":"document actions","depth":1,"bounds":{"left":0.56582445,"top":1.0,"width":0.0033244682,"height":-0.02394259},"on_screen":true,"role_description":"menu button","is_enabled":false,"is_focused":false},{"role":"AXStaticText","text":"compact_monitor_1_1778089220643.mp4","depth":1,"bounds":{"left":0.47240692,"top":1.0,"width":0.093417555,"height":-0.02394259},"on_screen":true,"role_description":"text"}]...
|
4831438804573237104
|
7082805162878442102
|
click
|
hybrid
|
NULL
|
rewind
play/pause
fast forward
More Controls
toggl rewind
play/pause
fast forward
More Controls
toggle full screen
show external playback menu
show external playback menu
show media selection menu
toggle picture-in-picture playback
show action menu
share
show chapter menu
zoom
zoom
playback speed
00:03
toggle elapsed time, timecode and framecount
02:10
toggle duration and remaining time
document actions
compact_monitor_1_1778089220643.mp4
DMSAC.MILVAll 4DMsloastApp[no preview availablel11 | 10:00 AMIMonday. May 4th-7 Jira Cloud@ 15 Monday@Nikolay Ivanov transitioned aBug you are watching from Code...Wednesday, April 29thAneliva AngelovaWednesdayStoyan Tanev6 DMWednesdavнаша стоананTuesday. April 28th?1 Stefka StoyanovaApr 28thтия тикети е добре да влезнат вдругия спринт ли? сложете някакви...Ves@ Thread in DM: исках да те...смени го в Circle Cl env на новиятокен който си напларилApr 28thStefka Stoyano… Replied Apr 28thAOMIпnuaтна oтлуска СStetka Stovanova and …... Aor 28thl•• 0‹→ сN& Adelina Petrova "Pull requests • screenpipe/screenpipe • GitHubMessagesLo Add canvasUr Files# Hostinger login | Sign in to Hostinger accountне, само стр се тракватLogin - Nginx Proxy ManagerLukas Kovalik IN 1:15 PM* Screenpipe - ArchiveAdelina Petrova "T 1:42 PMpagesLukas Kovalik "T 1:43 PMЯСНО@ SQLite Web: archive.db©SQLite Web: db.sqliteAdelina Petrova 5:06 PMда не ои проолема да е заради това кю: QUEUE,DELAYANew TabLukas Kovalik * 5:06 PMscreenpipe/,claude/skills at main • screenpipe/screenpза това искам да дооавя логовеAdelina Petrova 5:07 PMUAVDA MO CTAUG SUA rA MaVUOLI?има ли риск за нещоLukas Kovalik " 5:08 PMвсишност нама опашка тукаAdelina Petrova " 5:12 PM• сега, няма ли ла сложи евента в това кю и ла цака изпьл.Lukas Kovalik *T 5:21 PMла, ше оставя detault изпь лнениеLukas Kovalik 1K 5-26 PMпо поинцип го направих като nudge-created че те не са о!•и глелам че и този event няма никойAdelina Petrova" 5:33PMспорел мен пробвай без това кюLukas Kovalik * 5:33 PMhttps://run.userpilot.io/events/tracked_event/10run.userpilot.ioUserpilotUserpilot helos product teams deliver personalized in-appgrowth metrics at every stage of the user lournev.не е това обаче, гледам че всички си минават през сьщиAdelina Petrova * 5:40 PMами эко можеш сложи тогава лог да го видимAdelina Petrova has paused their notificationsMessage Adelina Petrova " VacationingAaO Not Secure http:/[IP_ADDRESS]:8768/audio_transcriptions_fts_idx/audio_tagsaualo transcriptionsaudio_transcriptions_fts (v)audio_transcriptions_audio_transcriptions_.audio_transcriptions_...elementselements_fts (v)elements_fts_configelements_fts_dataelements_fts_idxframesframes_fts (")frames_fts_configframes_fts_dataframes_fts_idxmeetingsmemoriesmemories_fts (v)memories_fts_configmemories_fts_datamemories_fts_idxocr_textpipe_executionspipe_scheduler_statesecretsspeaker_embeddingsspeakerssqlite_sequencesqlite_statlsalite_statatagsui_eventsui_events_fts (v)ui_events_fts_configui_events_fts_dataui_events_fts_idxvideo_chunksvision_tagsCREATE TABLE 'audio_transcriptions_fts_idx' (segid,term,PRIMARY KEY(segid, term)ColumnsColumnData typesegidpgnoIndexesNameColumnsSQLite database browser v0.7.2, powered by Flask and Peewee. © 2026 Charles LeiferToggle helper tablesAllow nullUniquePrimary keySOL432OSOEOEActionsread-onlyread-onlyread-onlyDrop?...
|
95
|
/Users/lukas/.screenpipe/data/data/2026-05-06/comp /Users/lukas/.screenpipe/data/data/2026-05-06/compact_monitor_1_1778089220643.mp4...
|
NULL
|
NULL
|
|
98
|
7
|
9
|
2026-05-06T17:43:33.548086+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778089413548_m1.jpg...
|
QuickTime Player
|
compact_monitor_1_1778089220643.mp4
|
True
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
iTerm2
Shell
Edit
View
Session
Scripts
Profiles
Wi iTerm2
Shell
Edit
View
Session
Scripts
Profiles
Window
Help
Q
> 0
G
94% 142
8
Wed 6 May 20:27:39
screenpipe"
で81
DOCKER
api auth
encrypt
secrets
retention days
retention mode
DEV (docker)
#2.
APP (-zsh)
283
-zsh.
エ4
screenpipe*
885
-zsh
36
enabled
disabled
7
Q- you
<>X
media-only (keep transcripts)
languages
all languages
monitors
id: 1
id: 2
audio devices
MacBook Pro Microphone (input)
System Audio (output)
are using local processing. all
your data stays on your computer.
warning: telemetry is enabled. only error-level data will be sent.
to disable, use the --disable-telemetry flag.
check
latest changes here: https://github.com/screenpipe/screenpipe/releases
2026-05-0620:27:34.638384Z
INFO
screenpipe: starting UI event capture
2026-05-06720:27:34.6376792
INFO
screenpipe_core: :pipes:
pipe scheduler started (generation 2)
2026-05-06T20:27:34.649154Z
INFO
screenpipe_engine:: power: :manager:
initial
power profile: Performance
Con_ac=true, battery=Some(94))
2026-05-06120:27:34.6527942
WARN
screenpipe: pi
agent install failed: bun not found - install from https://bun.sh
2026-05-06120:27:34.6558392
INFO
screenpipe_engine: :ui_recorder: Starting UI event capture
2026-05-06T20:27:34.6738772
INFO
screenpipe_engine::ui_recorder: UI recording session started: 54869993-7b4b-491f-b717-2a583517f9c5
2026-05-06T20:27:34.673910Z
INFO
screenpipe_engine:: calendar_speaker_id: speaker identification: started (user_name=<not set>)
2026-05-0620:27:34.6740572
INFO
screenpipe_engine: hot_frame_cache: hot_frame_cache: warming from DB (2026-05-05 17:27:34.674056 UTC to 2026-05-06 17:27:34.674056 UTC
2026-05-06120:27:34.6748922
INFO
2026-05-06T20:27:34.675788Z
INFO
screenpipe_engine: meeting_detector: meeting v2: detection loop started (base_interval=5s, profiles=12)
2026-05-0620:27:34.686546Z
INFO
screenpipe_engine: hot_frame_cache: hot_frame_cache: warmed with 0 frame entries, coverage from 2026-05-05 17:27:34.674056 UTC
screenpipe_engine::server: Server listening on [IP_ADDRESS]:3030
2026-05-06120:27:34.6913712
INFO
screenpipe_connect: mdns: mdns: advertising screenpipe on port 3030
2026-05-06T20:27:36.270608Z
INFO
screenpipe_engine: vision_manager::manager: Starting vision recording
2026-05-06T20:27:36.270669Z
INFO
screenpipe_engine: :vision_manager::manager: Starting event-driven capture for
2026-05-06T20:27:36.270714Z
INFO
screenpipe_engine:: event_driven_capture: event-driven capture started for monitor 1 (device: monitor_1)
2026-05-0620:27:36.932583Z
INFO
screenpipe_engine: vision_manager: :manager: Starting vision recording for monitor 2 (3008×1253)
2026-05-06T20:27:36.9328527
INFO
screenpipe_engine:: vision_manager: managfr: Starting event-driven capture for monitor 2 (device: monitor_2)
2026-05-0620:27:36.9328827
INFO
screenpipe_engine:: vision_manager::manager: VisionManager started with 2/2 monitor(s)
2026-05-06120:27:36.9328992
INFO
screenpipe_engine:: vision_manager: monitor_watcher: Starting monitor watcher (event-driven via CGDisplayRegisterReconfigurationCallback, 60s bac
kstop poll)
2026-05-0620:27:36.932901Z
2026-05-06720:27:39.1582812
INFO
INFO
screenpipe_engine:: event_driven_capture: event-driven capture started for monitor 2 (device: monitor_2)
sck_rs:: stream_manager:
persistent SCK stream started for display 1 1440x900, 2fps, 3 excluded)
Analyse Image
rewind
play/pause
fast forward
More Controls
toggle full screen
show external playback menu
show external playback menu
show media selection menu
toggle picture-in-picture playback
show action menu
share
show chapter menu
zoom
zoom
playback speed
00:04
toggle elapsed time, timecode and framecount
02:10
toggle duration and remaining time
document actions
compact_monitor_1_1778089220643.mp4...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"iTerm2","depth":2,"bounds":{"left":0.06308535,"top":0.032192513,"width":0.032542154,"height":0.01604133},"on_screen":true,"value":"iTerm2","role_description":"text entry area","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"Shell","depth":2,"bounds":{"left":0.10832526,"top":0.034560725,"width":0.021196704,"height":0.013565891},"on_screen":true,"value":"Shell","role_description":"text entry area","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"Edit","depth":2,"bounds":{"left":0.14223999,"top":0.034560725,"width":0.016957365,"height":0.011304909},"on_screen":true,"value":"Edit","role_description":"text entry area","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"View","depth":2,"bounds":{"left":0.17191538,"top":0.034560725,"width":0.021196704,"height":0.013565891},"on_screen":true,"value":"View","role_description":"text entry area","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"Session","depth":2,"bounds":{"left":0.20438232,"top":0.03210735,"width":0.033984087,"height":0.016211655},"on_screen":true,"value":"Session","role_description":"text entry area","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"Scripts","depth":2,"bounds":{"left":0.251041,"top":0.03450921,"width":0.031105999,"height":0.0136689115},"on_screen":true,"value":"Scripts","role_description":"text entry area","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"Profiles","depth":2,"bounds":{"left":0.29344314,"top":0.034560725,"width":0.032501616,"height":0.013565891},"on_screen":true,"value":"Profiles","role_description":"text entry area","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"Window","depth":2,"bounds":{"left":0.3386628,"top":0.034560725,"width":0.033914726,"height":0.013565891},"on_screen":true,"value":"Window","role_description":"text entry area","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"Help","depth":2,"bounds":{"left":0.38388243,"top":0.034560725,"width":0.021196704,"height":0.013565891},"on_screen":true,"value":"Help","role_description":"text entry area","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"Q","depth":2,"bounds":{"left":0.6467216,"top":0.032299742,"width":0.015544251,"height":0.018087855},"on_screen":true,"value":"Q","role_description":"text entry area","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"> 0","depth":2,"bounds":{"left":0.6947674,"top":0.032098766,"width":0.022609819,"height":0.020549813},"on_screen":true,"value":"> 0","role_description":"text entry area","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"G","depth":2,"bounds":{"left":0.751292,"top":0.034560725,"width":0.009891796,"height":0.015826873},"on_screen":true,"value":"G","role_description":"text entry area","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"94% 142","depth":2,"bounds":{"left":0.8275917,"top":0.034502253,"width":0.036757756,"height":0.013682831},"on_screen":true,"value":"94% 142","role_description":"text entry area","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"8","depth":2,"bounds":{"left":0.8770591,"top":0.032299742,"width":0.011304909,"height":0.018087855},"on_screen":true,"value":"8","role_description":"text entry area","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"Wed 6 May 20:27:39","depth":2,"bounds":{"left":0.89966893,"top":0.032098766,"width":0.08902616,"height":0.016203703},"on_screen":true,"value":"Wed 6 May 20:27:39","role_description":"text entry area","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"screenpipe\"","depth":2,"bounds":{"left":0.48703972,"top":0.061692506,"width":0.055111434,"height":0.015826873},"on_screen":true,"value":"screenpipe\"","role_description":"text entry area","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"で81","depth":2,"bounds":{"left":0.97173774,"top":0.06126543,"width":0.022609819,"height":0.01404321},"on_screen":true,"value":"で81","role_description":"text entry area","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"DOCKER\napi auth\nencrypt\nsecrets\nretention days\nretention mode","depth":2,"bounds":{"left":0.0404958,"top":0.09087725,"width":0.0833737,"height":0.09785731},"on_screen":true,"lines":[{"char_start":0,"char_count":7,"bounds":{"left":0.07720473,"top":0.09087725,"width":0.033978797,"height":0.013981927}},{"char_start":7,"char_count":9,"bounds":{"left":0.041819755,"top":0.115276,"width":0.045397956,"height":0.017187012}},{"char_start":16,"char_count":8,"bounds":{"left":0.041879702,"top":0.136109,"width":0.04103872,"height":0.016218718}},{"char_start":24,"char_count":8,"bounds":{"left":0.0814761,"top":0.13630491,"width":0.04239341,"height":0.013565891}},{"char_start":32,"char_count":15,"bounds":{"left":0.0404958,"top":0.15416667,"width":0.077721246,"height":0.016203703}},{"char_start":47,"char_count":14,"bounds":{"left":0.041908916,"top":0.17248061,"width":0.07630814,"height":0.016253948}}],"value":"DOCKER\napi auth\nencrypt\nsecrets\nretention days\nretention mode","role_description":"text entry area","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"DEV (docker)","depth":2,"bounds":{"left":0.23267926,"top":0.09334625,"width":0.04945898,"height":0.011304908},"on_screen":true,"value":"DEV (docker)","role_description":"text entry area","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"#2.\nAPP (-zsh)","depth":2,"bounds":{"left":0.328771,"top":0.09081737,"width":0.108843744,"height":0.01410169},"on_screen":true,"value":"#2.\nAPP (-zsh)","role_description":"text entry area","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"283","depth":2,"bounds":{"left":0.48703972,"top":0.09334625,"width":0.012718023,"height":0.011304909},"on_screen":true,"value":"283","role_description":"text entry area","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"-zsh.","depth":2,"bounds":{"left":0.5675872,"top":0.09334625,"width":0.018370477,"height":0.011304909},"on_screen":true,"value":"-zsh.","role_description":"text entry area","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"エ4","depth":2,"bounds":{"left":0.6467216,"top":0.09334625,"width":0.012718024,"height":0.011304909},"on_screen":true,"value":"エ4","role_description":"text entry area","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"screenpipe*","depth":2,"bounds":{"left":0.71312386,"top":0.090964265,"width":0.045247752,"height":0.013807908},"on_screen":true,"value":"screenpipe*","role_description":"text entry area","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"885","depth":2,"bounds":{"left":0.8049903,"top":0.09108527,"width":0.014405909,"height":0.0135658905},"on_screen":true,"value":"885","role_description":"text entry area","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"-zsh","depth":2,"bounds":{"left":0.8855378,"top":0.09334625,"width":0.019783592,"height":0.011304909},"on_screen":true,"value":"-zsh","role_description":"text entry area","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"36","depth":2,"bounds":{"left":0.96467215,"top":0.09108527,"width":0.014131136,"height":0.0135658905},"on_screen":true,"value":"36","role_description":"text entry area","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"enabled\ndisabled\n7","depth":2,"bounds":{"left":0.17612582,"top":0.11573701,"width":0.04525824,"height":0.05222164},"on_screen":true,"lines":[{"char_start":0,"char_count":8,"bounds":{"left":0.17612582,"top":0.11573701,"width":0.03962495,"height":0.014004003}},{"char_start":8,"char_count":9,"bounds":{"left":0.176145,"top":0.13397257,"width":0.045239065,"height":0.015969597}},{"char_start":17,"char_count":1,"bounds":{"left":0.17615472,"top":0.15213178,"width":0.007065568,"height":0.015826873}}],"value":"enabled\ndisabled\n7","role_description":"text entry area","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"Q- you","depth":2,"bounds":{"left":0.79792476,"top":0.13364197,"width":0.032501616,"height":0.018489808},"on_screen":true,"value":"Q- you","role_description":"text entry area","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<>X","depth":2,"bounds":{"left":0.9307574,"top":0.13364197,"width":0.036740955,"height":0.018489808},"on_screen":true,"value":"<>X","role_description":"text entry area","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"media-only (keep transcripts)","depth":2,"bounds":{"left":0.17615472,"top":0.17248063,"width":0.15826872,"height":0.018414441},"on_screen":true,"value":"media-only (keep transcripts)","role_description":"text entry area","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"languages","depth":2,"bounds":{"left":0.040414415,"top":0.21031201,"width":0.051034864,"height":0.019298458},"on_screen":true,"value":"languages","role_description":"text entry area","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"all languages","depth":2,"bounds":{"left":0.17615472,"top":0.2308642,"width":0.072068796,"height":0.018489808},"on_screen":true,"value":"all languages","role_description":"text entry area","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"monitors","depth":2,"bounds":{"left":0.0404958,"top":0.26970285,"width":0.045219637,"height":0.015826873},"on_screen":true,"value":"monitors","role_description":"text entry area","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"id: 1\nid: 2","depth":2,"bounds":{"left":0.17615472,"top":0.29005167,"width":0.028262274,"height":0.03391473},"on_screen":true,"lines":[{"char_start":0,"char_count":6,"bounds":{"left":0.17615472,"top":0.29005167,"width":0.028262274,"height":0.015826873}},{"char_start":6,"char_count":5,"bounds":{"left":0.17615472,"top":0.31040052,"width":0.028262274,"height":0.0135658905}}],"value":"id: 1\nid: 2","role_description":"text entry area","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"audio devices","depth":2,"bounds":{"left":0.040495805,"top":0.34861112,"width":0.07348191,"height":0.01404321},"on_screen":true,"value":"audio devices","role_description":"text entry area","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"MacBook Pro Microphone (input)\nSystem Audio (output)","depth":2,"bounds":{"left":0.17615472,"top":0.36692506,"width":0.16392119,"height":0.038939133},"on_screen":true,"lines":[{"char_start":0,"char_count":31,"bounds":{"left":0.17615472,"top":0.36692506,"width":0.16392119,"height":0.018414441}},{"char_start":31,"char_count":21,"bounds":{"left":0.17615472,"top":0.3872739,"width":0.114462204,"height":0.018590294}}],"value":"MacBook Pro Microphone (input)\nSystem Audio (output)","role_description":"text entry area","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"are using local processing. all\nyour data stays on your computer.","depth":2,"bounds":{"left":0.051800717,"top":0.42530864,"width":0.35327843,"height":0.018489808},"on_screen":true,"value":"are using local processing. all\nyour data stays on your computer.","role_description":"text entry area","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"warning: telemetry is enabled. only error-level data will be sent.\nto disable, use the --disable-telemetry flag.","depth":2,"bounds":{"left":0.030604003,"top":0.4641473,"width":0.35751775,"height":0.041099627},"on_screen":true,"lines":[{"char_start":0,"char_count":67,"bounds":{"left":0.030604022,"top":0.4641473,"width":0.35751775,"height":0.018414441}},{"char_start":67,"char_count":45,"bounds":{"left":0.030604003,"top":0.48449612,"width":0.24446866,"height":0.020750789}}],"value":"warning: telemetry is enabled. only error-level data will be sent.\nto disable, use the --disable-telemetry flag.","role_description":"text entry area","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"check\nlatest changes here: https://github.com/screenpipe/screenpipe/releases\n2026-05-0620:27:34.638384Z\nINFO\nscreenpipe: starting UI event capture\n2026-05-06720:27:34.6376792\nINFO\nscreenpipe_core: :pipes:\npipe scheduler started (generation 2)\n2026-05-06T20:27:34.649154Z\nINFO\nscreenpipe_engine:: power: :manager:\ninitial\npower profile: Performance\nCon_ac=true, battery=Some(94))\n2026-05-06120:27:34.6527942\nWARN\nscreenpipe: pi\nagent install failed: bun not found - install from https://bun.sh\n2026-05-06120:27:34.6558392\nINFO\nscreenpipe_engine: :ui_recorder: Starting UI event capture\n2026-05-06T20:27:34.6738772\nINFO\nscreenpipe_engine::ui_recorder: UI recording session started: 54869993-7b4b-491f-b717-2a583517f9c5\n2026-05-06T20:27:34.673910Z\nINFO\nscreenpipe_engine:: calendar_speaker_id: speaker identification: started (user_name=<not set>)\n2026-05-0620:27:34.6740572\nINFO\nscreenpipe_engine: hot_frame_cache: hot_frame_cache: warming from DB (2026-05-05 17:27:34.674056 UTC to 2026-05-06 17:27:34.674056 UTC\n2026-05-06120:27:34.6748922\nINFO\n2026-05-06T20:27:34.675788Z\nINFO\nscreenpipe_engine: meeting_detector: meeting v2: detection loop started (base_interval=5s, profiles=12)\n2026-05-0620:27:34.686546Z\nINFO\nscreenpipe_engine: hot_frame_cache: hot_frame_cache: warmed with 0 frame entries, coverage from 2026-05-05 17:27:34.674056 UTC\nscreenpipe_engine::server: Server listening on 127.0.0.1:3030\n2026-05-06120:27:34.6913712\nINFO\nscreenpipe_connect: mdns: mdns: advertising screenpipe on port 3030\n2026-05-06T20:27:36.270608Z\nINFO\nscreenpipe_engine: vision_manager::manager: Starting vision recording\n2026-05-06T20:27:36.270669Z\nINFO\nscreenpipe_engine: :vision_manager::manager: Starting event-driven capture for\n2026-05-06T20:27:36.270714Z\nINFO\nscreenpipe_engine:: event_driven_capture: event-driven capture started for monitor 1 (device: monitor_1)\n2026-05-0620:27:36.932583Z\nINFO\nscreenpipe_engine: vision_manager: :manager: Starting vision recording for monitor 2 (3008×1253)\n2026-05-06T20:27:36.9328527\nINFO\nscreenpipe_engine:: vision_manager: managfr: Starting event-driven capture for monitor 2 (device: monitor_2)\n2026-05-0620:27:36.9328827\nINFO\nscreenpipe_engine:: vision_manager::manager: VisionManager started with 2/2 monitor(s)\n2026-05-06120:27:36.9328992\nINFO\nscreenpipe_engine:: vision_manager: monitor_watcher: Starting monitor watcher (event-driven via CGDisplayRegisterReconfigurationCallback, 60s bac\nkstop poll)\n2026-05-0620:27:36.932901Z\n2026-05-06720:27:39.1582812\nINFO\nINFO\nscreenpipe_engine:: event_driven_capture: event-driven capture started for monitor 2 (device: monitor_2)\nsck_rs:: stream_manager:\npersistent SCK stream started for display 1 1440x900, 2fps, 3 excluded)","depth":2,"bounds":{"left":0.030604005,"top":0.52253085,"width":0.96374357,"height":0.44830248},"on_screen":true,"value":"check\nlatest changes here: https://github.com/screenpipe/screenpipe/releases\n2026-05-0620:27:34.638384Z\nINFO\nscreenpipe: starting UI event capture\n2026-05-06720:27:34.6376792\nINFO\nscreenpipe_core: :pipes:\npipe scheduler started (generation 2)\n2026-05-06T20:27:34.649154Z\nINFO\nscreenpipe_engine:: power: :manager:\ninitial\npower profile: Performance\nCon_ac=true, battery=Some(94))\n2026-05-06120:27:34.6527942\nWARN\nscreenpipe: pi\nagent install failed: bun not found - install from https://bun.sh\n2026-05-06120:27:34.6558392\nINFO\nscreenpipe_engine: :ui_recorder: Starting UI event capture\n2026-05-06T20:27:34.6738772\nINFO\nscreenpipe_engine::ui_recorder: UI recording session started: 54869993-7b4b-491f-b717-2a583517f9c5\n2026-05-06T20:27:34.673910Z\nINFO\nscreenpipe_engine:: calendar_speaker_id: speaker identification: started (user_name=<not set>)\n2026-05-0620:27:34.6740572\nINFO\nscreenpipe_engine: hot_frame_cache: hot_frame_cache: warming from DB (2026-05-05 17:27:34.674056 UTC to 2026-05-06 17:27:34.674056 UTC\n2026-05-06120:27:34.6748922\nINFO\n2026-05-06T20:27:34.675788Z\nINFO\nscreenpipe_engine: meeting_detector: meeting v2: detection loop started (base_interval=5s, profiles=12)\n2026-05-0620:27:34.686546Z\nINFO\nscreenpipe_engine: hot_frame_cache: hot_frame_cache: warmed with 0 frame entries, coverage from 2026-05-05 17:27:34.674056 UTC\nscreenpipe_engine::server: Server listening on 127.0.0.1:3030\n2026-05-06120:27:34.6913712\nINFO\nscreenpipe_connect: mdns: mdns: advertising screenpipe on port 3030\n2026-05-06T20:27:36.270608Z\nINFO\nscreenpipe_engine: vision_manager::manager: Starting vision recording\n2026-05-06T20:27:36.270669Z\nINFO\nscreenpipe_engine: :vision_manager::manager: Starting event-driven capture for\n2026-05-06T20:27:36.270714Z\nINFO\nscreenpipe_engine:: event_driven_capture: event-driven capture started for monitor 1 (device: monitor_1)\n2026-05-0620:27:36.932583Z\nINFO\nscreenpipe_engine: vision_manager: :manager: Starting vision recording for monitor 2 (3008×1253)\n2026-05-06T20:27:36.9328527\nINFO\nscreenpipe_engine:: vision_manager: managfr: Starting event-driven capture for monitor 2 (device: monitor_2)\n2026-05-0620:27:36.9328827\nINFO\nscreenpipe_engine:: vision_manager::manager: VisionManager started with 2/2 monitor(s)\n2026-05-06120:27:36.9328992\nINFO\nscreenpipe_engine:: vision_manager: monitor_watcher: Starting monitor watcher (event-driven via CGDisplayRegisterReconfigurationCallback, 60s bac\nkstop poll)\n2026-05-0620:27:36.932901Z\n2026-05-06720:27:39.1582812\nINFO\nINFO\nscreenpipe_engine:: event_driven_capture: event-driven capture started for monitor 2 (device: monitor_2)\nsck_rs:: stream_manager:\npersistent SCK stream started for display 1 1440x900, 2fps, 3 excluded)","role_description":"text entry area","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Analyse Image","depth":2,"bounds":{"left":0.975,"top":0.96,"width":0.018055556,"height":0.028888889},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"rewind","depth":1,"bounds":{"left":0.47916666,"top":0.7861111,"width":0.017361112,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXCheckBox","text":"play/pause","depth":1,"bounds":{"left":0.50381947,"top":0.77666664,"width":0.02013889,"height":0.037777778},"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":true},{"role":"AXButton","text":"fast forward","depth":1,"bounds":{"left":0.5315972,"top":0.7861111,"width":0.017361112,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"More Controls","depth":1,"bounds":{"left":0.653125,"top":0.78555554,"width":0.0125,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXCheckBox","text":"toggle full screen","depth":1,"bounds":{"left":0.590625,"top":0.7916667,"width":0.013888889,"height":0.022222223},"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"show external playback menu","depth":1,"bounds":{"left":0.590625,"top":0.78444445,"width":0.013888889,"height":0.022222223},"on_screen":true,"role_description":"button","is_focused":false},{"role":"AXButton","text":"show external playback menu","depth":2,"bounds":{"left":0.590625,"top":0.78444445,"width":0.013888889,"height":0.022222223},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"show media selection menu","depth":1,"bounds":{"left":0.590625,"top":0.7916667,"width":0.015277778,"height":0.022222223},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"toggle picture-in-picture playback","depth":1,"bounds":{"left":0.6170139,"top":0.7838889,"width":0.017361112,"height":0.022222223},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"show action menu","depth":1,"bounds":{"left":0.590625,"top":0.7911111,"width":0.014583333,"height":0.023333333},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"share","depth":1,"bounds":{"left":0.646875,"top":0.78055555,"width":0.013541667,"height":0.025555555},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"show chapter menu","depth":1,"bounds":{"left":0.590625,"top":0.79444444,"width":0.014583333,"height":0.016666668},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXCheckBox","text":"zoom","depth":1,"bounds":{"left":0.590625,"top":0.78944445,"width":0.013888889,"height":0.026666667},"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXCheckBox","text":"zoom","depth":1,"bounds":{"left":0.590625,"top":0.7922222,"width":0.017361112,"height":0.02111111},"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"playback speed","depth":1,"bounds":{"left":0.590625,"top":0.7922222,"width":0.013194445,"height":0.02111111},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXStaticText","text":"00:04","depth":1,"bounds":{"left":0.36215279,"top":0.82277775,"width":0.02638889,"height":0.016666668},"on_screen":true,"role_description":"text"},{"role":"AXCheckBox","text":"toggle elapsed time, timecode and framecount","depth":1,"bounds":{"left":0.36354166,"top":0.82277775,"width":0.023611112,"height":0.016666668},"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXStaticText","text":"02:10","depth":1,"bounds":{"left":0.6340278,"top":0.82277775,"width":0.031597223,"height":0.016666668},"on_screen":true,"role_description":"text"},{"role":"AXCheckBox","text":"toggle duration and remaining time","depth":1,"bounds":{"left":0.6354167,"top":0.82277775,"width":0.028819444,"height":0.016666668},"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXMenuButton","text":"document actions","depth":1,"bounds":{"left":0.6173611,"top":0.033333335,"width":0.0069444445,"height":0.017777778},"on_screen":true,"role_description":"menu button","is_enabled":false,"is_focused":false},{"role":"AXStaticText","text":"compact_monitor_1_1778089220643.mp4","depth":1,"bounds":{"left":0.42222223,"top":0.033333335,"width":0.19513889,"height":0.017777778},"on_screen":true,"role_description":"text"}]...
|
-8720135604288379975
|
4756416446518213684
|
click
|
accessibility
|
NULL
|
iTerm2
Shell
Edit
View
Session
Scripts
Profiles
Wi iTerm2
Shell
Edit
View
Session
Scripts
Profiles
Window
Help
Q
> 0
G
94% 142
8
Wed 6 May 20:27:39
screenpipe"
で81
DOCKER
api auth
encrypt
secrets
retention days
retention mode
DEV (docker)
#2.
APP (-zsh)
283
-zsh.
エ4
screenpipe*
885
-zsh
36
enabled
disabled
7
Q- you
<>X
media-only (keep transcripts)
languages
all languages
monitors
id: 1
id: 2
audio devices
MacBook Pro Microphone (input)
System Audio (output)
are using local processing. all
your data stays on your computer.
warning: telemetry is enabled. only error-level data will be sent.
to disable, use the --disable-telemetry flag.
check
latest changes here: https://github.com/screenpipe/screenpipe/releases
2026-05-0620:27:34.638384Z
INFO
screenpipe: starting UI event capture
2026-05-06720:27:34.6376792
INFO
screenpipe_core: :pipes:
pipe scheduler started (generation 2)
2026-05-06T20:27:34.649154Z
INFO
screenpipe_engine:: power: :manager:
initial
power profile: Performance
Con_ac=true, battery=Some(94))
2026-05-06120:27:34.6527942
WARN
screenpipe: pi
agent install failed: bun not found - install from https://bun.sh
2026-05-06120:27:34.6558392
INFO
screenpipe_engine: :ui_recorder: Starting UI event capture
2026-05-06T20:27:34.6738772
INFO
screenpipe_engine::ui_recorder: UI recording session started: 54869993-7b4b-491f-b717-2a583517f9c5
2026-05-06T20:27:34.673910Z
INFO
screenpipe_engine:: calendar_speaker_id: speaker identification: started (user_name=<not set>)
2026-05-0620:27:34.6740572
INFO
screenpipe_engine: hot_frame_cache: hot_frame_cache: warming from DB (2026-05-05 17:27:34.674056 UTC to 2026-05-06 17:27:34.674056 UTC
2026-05-06120:27:34.6748922
INFO
2026-05-06T20:27:34.675788Z
INFO
screenpipe_engine: meeting_detector: meeting v2: detection loop started (base_interval=5s, profiles=12)
2026-05-0620:27:34.686546Z
INFO
screenpipe_engine: hot_frame_cache: hot_frame_cache: warmed with 0 frame entries, coverage from 2026-05-05 17:27:34.674056 UTC
screenpipe_engine::server: Server listening on [IP_ADDRESS]:3030
2026-05-06120:27:34.6913712
INFO
screenpipe_connect: mdns: mdns: advertising screenpipe on port 3030
2026-05-06T20:27:36.270608Z
INFO
screenpipe_engine: vision_manager::manager: Starting vision recording
2026-05-06T20:27:36.270669Z
INFO
screenpipe_engine: :vision_manager::manager: Starting event-driven capture for
2026-05-06T20:27:36.270714Z
INFO
screenpipe_engine:: event_driven_capture: event-driven capture started for monitor 1 (device: monitor_1)
2026-05-0620:27:36.932583Z
INFO
screenpipe_engine: vision_manager: :manager: Starting vision recording for monitor 2 (3008×1253)
2026-05-06T20:27:36.9328527
INFO
screenpipe_engine:: vision_manager: managfr: Starting event-driven capture for monitor 2 (device: monitor_2)
2026-05-0620:27:36.9328827
INFO
screenpipe_engine:: vision_manager::manager: VisionManager started with 2/2 monitor(s)
2026-05-06120:27:36.9328992
INFO
screenpipe_engine:: vision_manager: monitor_watcher: Starting monitor watcher (event-driven via CGDisplayRegisterReconfigurationCallback, 60s bac
kstop poll)
2026-05-0620:27:36.932901Z
2026-05-06720:27:39.1582812
INFO
INFO
screenpipe_engine:: event_driven_capture: event-driven capture started for monitor 2 (device: monitor_2)
sck_rs:: stream_manager:
persistent SCK stream started for display 1 1440x900, 2fps, 3 excluded)
Analyse Image
rewind
play/pause
fast forward
More Controls
toggle full screen
show external playback menu
show external playback menu
show media selection menu
toggle picture-in-picture playback
show action menu
share
show chapter menu
zoom
zoom
playback speed
00:04
toggle elapsed time, timecode and framecount
02:10
toggle duration and remaining time
document actions
compact_monitor_1_1778089220643.mp4...
|
NULL
|
/Users/lukas/.screenpipe/data/data/2026-05-06/comp /Users/lukas/.screenpipe/data/data/2026-05-06/compact_monitor_1_1778089220643.mp4...
|
NULL
|
NULL
|
|
99
|
8
|
9
|
2026-05-06T17:43:38.651874+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778089418651_m2.jpg...
|
QuickTime Player
|
compact_monitor_1_1778089220643.mp4
|
True
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
rewind
play/pause
fast forward
More Controls
toggl rewind
play/pause
fast forward
More Controls
toggle full screen
show external playback menu
show external playback menu
show media selection menu
toggle picture-in-picture playback
show action menu
share
show chapter menu
zoom
zoom
playback speed
00:21
toggle elapsed time, timecode and framecount
02:10
toggle duration and remaining time
document actions
compact_monitor_1_1778089220643.mp4...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"rewind","depth":1,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXCheckBox","text":"play/pause","depth":1,"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"fast forward","depth":1,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"More Controls","depth":1,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXCheckBox","text":"toggle full screen","depth":1,"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"show external playback menu","depth":1,"on_screen":true,"role_description":"button","is_focused":false},{"role":"AXButton","text":"show external playback menu","depth":2,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"show media selection menu","depth":1,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"toggle picture-in-picture playback","depth":1,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"show action menu","depth":1,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"share","depth":1,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"show chapter menu","depth":1,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXCheckBox","text":"zoom","depth":1,"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXCheckBox","text":"zoom","depth":1,"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"playback speed","depth":1,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXStaticText","text":"00:21","depth":1,"on_screen":true,"role_description":"text"},{"role":"AXCheckBox","text":"toggle elapsed time, timecode and framecount","depth":1,"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXStaticText","text":"02:10","depth":1,"on_screen":true,"role_description":"text"},{"role":"AXCheckBox","text":"toggle duration and remaining time","depth":1,"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXMenuButton","text":"document actions","depth":1,"bounds":{"left":0.56582445,"top":1.0,"width":0.0033244682,"height":-0.02394259},"on_screen":true,"role_description":"menu button","is_enabled":false,"is_focused":false},{"role":"AXStaticText","text":"compact_monitor_1_1778089220643.mp4","depth":1,"bounds":{"left":0.47240692,"top":1.0,"width":0.093417555,"height":-0.02394259},"on_screen":true,"role_description":"text"}]...
|
-3346061688027555612
|
7082805161804700406
|
click
|
hybrid
|
NULL
|
rewind
play/pause
fast forward
More Controls
toggl rewind
play/pause
fast forward
More Controls
toggle full screen
show external playback menu
show external playback menu
show media selection menu
toggle picture-in-picture playback
show action menu
share
show chapter menu
zoom
zoom
playback speed
00:21
toggle elapsed time, timecode and framecount
02:10
toggle duration and remaining time
document actions
compact_monitor_1_1778089220643.mp4
DMSAC.MILVAll 4DMsloastApp[no preview availablel11 | 10:00 AMIMonday. May 4th-7 Jira Cloud@ 15 Monday@Nikolay Ivanov transitioned aBug you are watching from Code...Wednesday, April 29thAneliva AngelovaWednesdayStoyan Tanev6 DMWednesdavнаша стоананTuesday. April 28th?1 Stefka StoyanovaApr 28thтия тикети е добре да влезнат вдругия спринт ли? сложете някакви...Ves@ Thread in DM: исках да те...смени го в Circle Cl env на новиятокен който си напларилApr 28thStefka Stoyano… Replied Apr 28thAOMIпnuaтна oтлуска СStetka Stovanova and …... Aor 28thl•• 0‹→ сN& Adelina Petrova "Pull requests • screenpipe/screenpipe • GitHubMessagesLo Add canvasUr Files# Hostinger login | Sign in to Hostinger accountне, само стр се тракватLogin - Nginx Proxy ManagerLukas Kovalik IN 1:15 PM* Screenpipe - ArchiveAdelina Petrova "T 1:42 PMpagesLukas Kovalik "T 1:43 PMЯСНО@ SQLite Web: archive.db©SQLite Web: db.sqliteAdelina Petrova 5:06 PMда не ои проолема да е заради това кю: QUEUE,DELAYANew TabLukas Kovalik * 5:06 PMscreenpipe/,claude/skills at main • screenpipe/screenpза това искам да дооавя логовеAdelina Petrova 5:07 PMUAVDA MO CTAUG SUA rA MaVUOLI?има ли риск за нещоLukas Kovalik " 5:08 PMвсишност нама опашка тукаAdelina Petrova " 5:12 PM• сега, няма ли ла сложи евента в това кю и ла цака изпьл.Lukas Kovalik *T 5:21 PMла, ше оставя detault изпь лнениеLukas Kovalik 1K 5-26 PMпо поинцип го направих като nudge-created че те не са о!•и глелам че и този event няма никойAdelina Petrova" 5:33PMспорел мен пробвай без това кюLukas Kovalik * 5:33 PMhttps://run.userpilot.io/events/tracked_event/10run.userpilot.ioUserpilotUserpilot helos product teams deliver personalized in-appgrowth metrics at every stage of the user lournev.не е това обаче, гледам че всички си минават през сьщиAdelina Petrova * 5:40 PMами эко можеш сложи тогава лог да го видимAdelina Petrova has paused their notificationsMessage Adelina Petrova " VacationingAaO Not Secure http:/[IP_ADDRESS]:8768/audio_transcriptions_fts_idx/audio_tagsaualo transcriptionsaudio_transcriptions_fts (v)audio_transcriptions_audio_transcriptions_.audio_transcriptions_...elementselements_fts (v)elements_fts_configelements_fts_dataelements_fts_idxframesframes_fts (")frames_fts_configframes_fts_dataframes_fts_idxmeetingsmemoriesmemories_fts (v)memories_fts_configmemories_fts_datamemories_fts_idxocr_textpipe_executionspipe_scheduler_statesecretsspeaker_embeddingsspeakerssqlite_sequencesqlite_statlsalite_statatagsui_eventsui_events_fts (v)ui_events_fts_configui_events_fts_dataui_events_fts_idxvideo_chunksvision_tagsCREATE TABLE 'audio_transcriptions_fts_idx' (segid,term,PRIMARY KEY(segid, term)ColumnsColumnData typesegidpgnoIndexesNameColumnsSQLite database browser v0.7.2, powered by Flask and Peewee. © 2026 Charles LeiferToggle helper tablesAllow nullUniquePrimary keySOLActionsread-onlyread-onlyread-onlyDrop?...
|
NULL
|
/Users/lukas/.screenpipe/data/data/2026-05-06/comp /Users/lukas/.screenpipe/data/data/2026-05-06/compact_monitor_1_1778089220643.mp4...
|
NULL
|
NULL
|
|
100
|
7
|
10
|
2026-05-06T17:43:38.732613+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778089418732_m1.jpg...
|
QuickTime Player
|
compact_monitor_1_1778089220643.mp4
|
True
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
rewind
play/pause
fast forward
More Controls
toggl rewind
play/pause
fast forward
More Controls
toggle full screen
show external playback menu
show external playback menu
show media selection menu
toggle picture-in-picture playback
show action menu
share
show chapter menu
zoom
zoom
playback speed
00:21
toggle elapsed time, timecode and framecount
02:10
toggle duration and remaining time
document actions
compact_monitor_1_1778089220643.mp4...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"rewind","depth":1,"bounds":{"left":0.47916666,"top":0.7861111,"width":0.017361112,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXCheckBox","text":"play/pause","depth":1,"bounds":{"left":0.50381947,"top":0.77666664,"width":0.02013889,"height":0.037777778},"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"fast forward","depth":1,"bounds":{"left":0.5315972,"top":0.7861111,"width":0.017361112,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"More Controls","depth":1,"bounds":{"left":0.653125,"top":0.78555554,"width":0.0125,"height":0.017777778},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXCheckBox","text":"toggle full screen","depth":1,"bounds":{"left":0.590625,"top":0.7916667,"width":0.013888889,"height":0.022222223},"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"show external playback menu","depth":1,"bounds":{"left":0.590625,"top":0.78444445,"width":0.013888889,"height":0.022222223},"on_screen":true,"role_description":"button","is_focused":false},{"role":"AXButton","text":"show external playback menu","depth":2,"bounds":{"left":0.590625,"top":0.78444445,"width":0.013888889,"height":0.022222223},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"show media selection menu","depth":1,"bounds":{"left":0.590625,"top":0.7916667,"width":0.015277778,"height":0.022222223},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"toggle picture-in-picture playback","depth":1,"bounds":{"left":0.6170139,"top":0.7838889,"width":0.017361112,"height":0.022222223},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"show action menu","depth":1,"bounds":{"left":0.590625,"top":0.7911111,"width":0.014583333,"height":0.023333333},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"share","depth":1,"bounds":{"left":0.646875,"top":0.78055555,"width":0.013541667,"height":0.025555555},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"show chapter menu","depth":1,"bounds":{"left":0.590625,"top":0.79444444,"width":0.014583333,"height":0.016666668},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXCheckBox","text":"zoom","depth":1,"bounds":{"left":0.590625,"top":0.78944445,"width":0.013888889,"height":0.026666667},"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXCheckBox","text":"zoom","depth":1,"bounds":{"left":0.590625,"top":0.7922222,"width":0.017361112,"height":0.02111111},"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXButton","text":"playback speed","depth":1,"bounds":{"left":0.590625,"top":0.7922222,"width":0.013194445,"height":0.02111111},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false},{"role":"AXStaticText","text":"00:21","depth":1,"bounds":{"left":0.36215279,"top":0.82277775,"width":0.02638889,"height":0.016666668},"on_screen":true,"role_description":"text"},{"role":"AXCheckBox","text":"toggle elapsed time, timecode and framecount","depth":1,"bounds":{"left":0.36354166,"top":0.82277775,"width":0.023611112,"height":0.016666668},"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXStaticText","text":"02:10","depth":1,"bounds":{"left":0.6340278,"top":0.82277775,"width":0.031597223,"height":0.016666668},"on_screen":true,"role_description":"text"},{"role":"AXCheckBox","text":"toggle duration and remaining time","depth":1,"bounds":{"left":0.6354167,"top":0.82277775,"width":0.028819444,"height":0.016666668},"on_screen":true,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false},{"role":"AXMenuButton","text":"document actions","depth":1,"bounds":{"left":0.6173611,"top":0.033333335,"width":0.0069444445,"height":0.017777778},"on_screen":true,"role_description":"menu button","is_enabled":false,"is_focused":false},{"role":"AXStaticText","text":"compact_monitor_1_1778089220643.mp4","depth":1,"bounds":{"left":0.42222223,"top":0.033333335,"width":0.19513889,"height":0.017777778},"on_screen":true,"role_description":"text"}]...
|
-3346061688027555612
|
7082805161804700406
|
click
|
hybrid
|
NULL
|
rewind
play/pause
fast forward
More Controls
toggl rewind
play/pause
fast forward
More Controls
toggle full screen
show external playback menu
show external playback menu
show media selection menu
toggle picture-in-picture playback
show action menu
share
show chapter menu
zoom
zoom
playback speed
00:21
toggle elapsed time, timecode and framecount
02:10
toggle duration and remaining time
document actions
compact_monitor_1_1778089220643.mp4
QuickTime Player•FileEditViewWindowHelp40compact_monitor_1_1778089220643.mp4 ~screenpipe"-zsh-rw--rw--rw--rw-i-rw-!-rW-I-rw-!-rw-I-rw--rw-l-rW--rw-!-rw-I-rw-i-rw--ГW--rw-i-rw-|-rw-i-rw-!-rW--rw--rw-I-rw-i-rw-l-rw-i-rw-I-rw--rw-l-rW-I-rw-!-rw-IDOCKERX1X2APP (-zsh)settingaudio chunk durationportaudio disabledvision disabledpause on DRM contentaudio enginevad enginedata directorydebug modetelemetryuse pii removaluse all monitorsignored windowsincluded windowscloud syncauto-destruct piddeepgram keyapi authencrypt secretsretention daysretention modelanguagesmonitorsaudio devicesDEV (docker)value30 seconds3030falsefalsefalseParakeetSilero/Users/lukas/.screenpipefalsetruetruetrue["Boosteroid"]disabled0not setenableddisabledmedia-only (keep transcripts)all languagesid: 1id: 2-rw-!-ГW--rw-MacBook Pro Microphone (input)System Audio (output)00:21-rw-are using local processing. alldata stays onyoucomputer.-rw--rw-lwarning: telemetry is enabled.only error-leveldata will be sent.to disable, use the --disable-telemetry flag.-rw-iluka!check latest changes here: https://github.com/screenpipe/screenpipe/releasesluka: 2026-05-06T20:27:34.6383847INFO screenpipe: starting UI event captureX4Gscreenpipe*97% <4Wed 6 May 20:43:391X1-zshX6X5Q- you‹ › x»02:10...
|
98
|
/Users/lukas/.screenpipe/data/data/2026-05-06/comp /Users/lukas/.screenpipe/data/data/2026-05-06/compact_monitor_1_1778089220643.mp4...
|
NULL
|
NULL
|