|
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
|
|
26
|
4
|
0
|
2026-05-06T17:30:23.310609+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778088623310_m2.jpg...
|
iTerm2
|
NULL
|
True
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
94% 52• Wed 6 May 20:30:23ActivityLateMoreSlackVi 94% 52• Wed 6 May 20:30:23ActivityLateMoreSlackVievJiminny …..yDratts & sent.88 DirectoriasAb External connections** Starredijiminny-x-integrati.platform-inner-teamE) Channels# ai-chapter# alerts# backend# bugs# confusion-clinic# curiosity lab# engineering# general# jiminny-bg# platform-ticketsi product aunches# random# releases# sofia-office# support# thank-yous# the people of jimi..ó- Direct messages(3) Aneliva Angelova. ...Stovan Tanev €Stefka Stoyanova7 Ves.% Galya Dimitrova E1e. Aneliva Angelova0 Vasil VasilevJames GrahamNikolav Ivanova Inkas Kovali•AnncmistonWindowHelp@ Describe what you are looking forJhra cloudHomeMessages 9+1 15 new messages XStatus: In Dey(NI Assienee: Nikolay IvanovPrioritv:MCommentMore actions.Jira Cloua Arr 4:58 PM@Nikolay Ivanov transitioned a Story you are watching from Code Review — Ready for DeploymentJY-20/40 Kelease AJ Panorama reports to customersStatus: Keady for DeploymentN Type: StoryNI Assignee: Nikolay IvanovT Priority: MediumThursdav. April 30thvJira Cloud APP 11:43 AM@Nikolay Ivanov transitioned a Story you are watching from Ready for Deployment — DeployedJY-20740 Release AJ Panorama reports to customersCtatue. MonlovodNI Accionoo- Nilolov Ivanoy1 Drioritu- ModiumJira Cloud APP 5:52 PM@Nikolay Ivanov transitioned a Bug you are watching from In Dev → Code ReviewJY-20699 Wrong formattine for summarv in the CRMStatus: Code Review• Tvne: BueNI Assienee: Nikolay Ivanov1 Prioritv: Medium@Nikolay Ivanov commented on a Bug you are watchingJY-20699 Wrong formatting for summary in the CRMRofaro ve Aftor• • 0O, Chat= Cowork">code+ New chat• Prolects8 Artifacts• customizeBulgarian citizenship application proces:Dawarich location tracking proiectViewing retention policy in screenpipeClean shot x video recording terminationHubSpot rate limit handling with executeUntitledScreen pipe. Is there ability…SMB mount access inconsistency betwe—What is the best switch can..Permiccion denied on screennine volumeScreenpipe sync database attachment eLast swimming outing with DaniDetinition of incarceratedChromecast remote volume buttons notSalesforce APl errors with OrganizationDaily activity summary from screenpipeMacBook unexpected restarts and kanjiSecurity patch review and testing guidarFood calorie values referenceTracking location historv from last weekScreennine WAL processing when stoorScreenpipe retention policy code location v3. Wipe local datarm -rf ~/.screenpipe/4. Clear npx cacherm -rf ~.npm/_npx5. Fresh startnpx screenpipealatest record --disable-audio --ignored-windows "Boosteroid" --retentioThat's it. Your NAS archive is untouched and the sync script will be re-created... wait, actually— vou just deleted ~/.screenpipe/ whichincludes screenpipe svnc.sh.Copv it out firstco ~ screenoine/screenoioe svnc.sh ~ screenoipe svnc.shDo that before sted 3. then after screenpide creates the fresh ~/. screenpipe/ directorv ornret run. move if back.mv ~/screenpipe sync.sh -/.screenpipe/screenpipe sync.shMondav. Mav 4thvJira Cloud APP 11:54 AM@Nikolay Ivanov transitioned a Bug vou are watchine from Code Review _ DeplovedJY-20699 Wrong formatting for summary in the CRMpawleeanhwa• Tvoe: BugNt Aecianos. Nitoley tuann1 Dinitr MadiomCommentMessage Jira Gloud+ ДаKeep going in Claude CodeSwitch to Claude Code and let Claude work directlv in vour reno.running and testing as it goes.Write a message…Open Claude CodeCannotAkyRelaunch to updatelK lukas. ProCiaudo ic Aland can make mictakes Plesco double-chock racnoncod...
|
NULL
|
-3005666593331542715
|
NULL
|
visual_change
|
ocr
|
NULL
|
94% 52• Wed 6 May 20:30:23ActivityLateMoreSlackVi 94% 52• Wed 6 May 20:30:23ActivityLateMoreSlackVievJiminny …..yDratts & sent.88 DirectoriasAb External connections** Starredijiminny-x-integrati.platform-inner-teamE) Channels# ai-chapter# alerts# backend# bugs# confusion-clinic# curiosity lab# engineering# general# jiminny-bg# platform-ticketsi product aunches# random# releases# sofia-office# support# thank-yous# the people of jimi..ó- Direct messages(3) Aneliva Angelova. ...Stovan Tanev €Stefka Stoyanova7 Ves.% Galya Dimitrova E1e. Aneliva Angelova0 Vasil VasilevJames GrahamNikolav Ivanova Inkas Kovali•AnncmistonWindowHelp@ Describe what you are looking forJhra cloudHomeMessages 9+1 15 new messages XStatus: In Dey(NI Assienee: Nikolay IvanovPrioritv:MCommentMore actions.Jira Cloua Arr 4:58 PM@Nikolay Ivanov transitioned a Story you are watching from Code Review — Ready for DeploymentJY-20/40 Kelease AJ Panorama reports to customersStatus: Keady for DeploymentN Type: StoryNI Assignee: Nikolay IvanovT Priority: MediumThursdav. April 30thvJira Cloud APP 11:43 AM@Nikolay Ivanov transitioned a Story you are watching from Ready for Deployment — DeployedJY-20740 Release AJ Panorama reports to customersCtatue. MonlovodNI Accionoo- Nilolov Ivanoy1 Drioritu- ModiumJira Cloud APP 5:52 PM@Nikolay Ivanov transitioned a Bug you are watching from In Dev → Code ReviewJY-20699 Wrong formattine for summarv in the CRMStatus: Code Review• Tvne: BueNI Assienee: Nikolay Ivanov1 Prioritv: Medium@Nikolay Ivanov commented on a Bug you are watchingJY-20699 Wrong formatting for summary in the CRMRofaro ve Aftor• • 0O, Chat= Cowork">code+ New chat• Prolects8 Artifacts• customizeBulgarian citizenship application proces:Dawarich location tracking proiectViewing retention policy in screenpipeClean shot x video recording terminationHubSpot rate limit handling with executeUntitledScreen pipe. Is there ability…SMB mount access inconsistency betwe—What is the best switch can..Permiccion denied on screennine volumeScreenpipe sync database attachment eLast swimming outing with DaniDetinition of incarceratedChromecast remote volume buttons notSalesforce APl errors with OrganizationDaily activity summary from screenpipeMacBook unexpected restarts and kanjiSecurity patch review and testing guidarFood calorie values referenceTracking location historv from last weekScreennine WAL processing when stoorScreenpipe retention policy code location v3. Wipe local datarm -rf ~/.screenpipe/4. Clear npx cacherm -rf ~.npm/_npx5. Fresh startnpx screenpipealatest record --disable-audio --ignored-windows "Boosteroid" --retentioThat's it. Your NAS archive is untouched and the sync script will be re-created... wait, actually— vou just deleted ~/.screenpipe/ whichincludes screenpipe svnc.sh.Copv it out firstco ~ screenoine/screenoioe svnc.sh ~ screenoipe svnc.shDo that before sted 3. then after screenpide creates the fresh ~/. screenpipe/ directorv ornret run. move if back.mv ~/screenpipe sync.sh -/.screenpipe/screenpipe sync.shMondav. Mav 4thvJira Cloud APP 11:54 AM@Nikolay Ivanov transitioned a Bug vou are watchine from Code Review _ DeplovedJY-20699 Wrong formatting for summary in the CRMpawleeanhwa• Tvoe: BugNt Aecianos. Nitoley tuann1 Dinitr MadiomCommentMessage Jira Gloud+ ДаKeep going in Claude CodeSwitch to Claude Code and let Claude work directlv in vour reno.running and testing as it goes.Write a message…Open Claude CodeCannotAkyRelaunch to updatelK lukas. ProCiaudo ic Aland can make mictakes Plesco double-chock racnoncod...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
28
|
4
|
1
|
2026-05-06T17:30:33.155338+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778088633155_m2.jpg...
|
iTerm2
|
NULL
|
True
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
ActivityLaterrireroxcalVIewHistorybookmarksToolsme ActivityLaterrireroxcalVIewHistorybookmarksToolsmelpJiminny... ~Jhra cloud→Dratts & sent.HomeMessages 9+88 DirectoriasAb External connections* Starredijiminny-x-integrati..platform-inner-teamE) Channels# ai-chapter# alerts# backend# bugs# confusion-clinic# curiosity lab# engineering# general# jiminny-bg# platform-ticketsi product launches# random# releases# sofia-office# support# thank-yous# the people of jimi..ó- Direct messages(3) Aneliva Angelova....Stovan Tanev €Stefka Stoyanova(% Galya Dimitrova E1e. Aneliva Angelova0 Vasil VasilevJames GrahamNikolav Ivanova Inkas Kovali1 15 new messages XStatus: In DeyPrioritv:MCommentMore actions.Jira Cloua Arr 4:58 PM@Nikolay Ivanov transitioned a Story you are watching from Code Review — Ready for DeploymentJY-20/40 Kelease AJ Panorama reports to customersStatus: Keady for DeploymentN Type: StoryNI Assignee: Nikolay IvanovT Priority: MediumThursdav. April 30thvJira Cloud APP 11:43 AM@Nikolay Ivanov transitioned a Story you are watching from Ready for Deployment — DeployedJY-20740 Release AJ Panorama reports to customersCtatue. MonlovodNI Accionoo. Nitolov lvanoy1 Drioritu- ModiumJira Cloud APP 5:52 PM@Nikolay Ivanov transitioned a Bug you are watching from In Dev → Code ReviewJY-20699 Wrong formattine for summarv in the CRMStatus: Code Review• Tvne: BueNI Assienee: Nikolay Ivanov1 Prioritv: Medium@Nikolay Ivanov commented on a Bug you are watchingJY-20699 Wrong formatting for summary in the CRMRofaro ve AftorMondav. Mav 4th vJira Cloud APP 11:54 AM@Nikolay Ivanov transitioned a Bug vou are watchine from Code Review _ DeplovedJY-20699 Wrong formatting for summary in the CRMpawleeanhwa© Tvoe: BugNt Aecianos. Nitoley tuann1 Dinitr MadiomCommentMessage Jira Gloud•Annc+ Да95% 5• wea o May 20'30'34• • 0Q, Chat°= Cowork<> Coat+ New chat• Prolects8t Artifacts• customizeBulgarian citizenship application proces:Dawarich location tracking proiectViewing retention policy in screenpipeClean shot x video recording terminationHubSpot rate limit handling with executeUntitledScreen pipe. Is there ability…SMB mount access inconsistency betwe—What is the best switch can..Permiccion denied on screennine volumeScreenpipe sync database attachment eLast swimming outing with DaniDetinition of incarceratedChromecast remote volume buttons notSalesforce APl errors with OrganizationDaily activity summary from screenpipeMacBook unexpected restarts and kanjiSecurity patch review and testing guidarFood calorie values referenceTracking location historv from last weekScreennine WAL orocessing when stoorScreenpipe retention policy code location v3. Wipe local datarm -rf ~/.screenpipe/4. Clear npx cacherm -rf ~.npm/_npx5. Fresh startnpx screenpipealatest record --disable-audio --ignored-windows "Boosteroid" --retentioThat's it. Your NAS archive is untouched and the sync script will be re-created... wait, actually— vou just deleted ~/.screenpipe/ whichincludes screenpipe svnc.sh.Copv it out firstco ~ screenoine/screenoioe svnc.sh ~ screenoipe svnc.shDo that before sted 3. then after screenpide creates the fresh ~/. screenpipe/ directorv ornret run. move if back:mv ~/screenpipe sync.sh -/.screenpipe/screenpipe sync.shKeep going in Claude CodeSwitch to Claude Code and let Claude work directlv in vour reno.running and testing as it goes.Write a message…Open Claude CodeCannotAkyRelaunch to updatelK lukas. ProCiaudo ic Aland can make mictakes Plesco double-chock racnoncod...
|
NULL
|
-4186607484453847494
|
NULL
|
visual_change
|
ocr
|
NULL
|
ActivityLaterrireroxcalVIewHistorybookmarksToolsme ActivityLaterrireroxcalVIewHistorybookmarksToolsmelpJiminny... ~Jhra cloud→Dratts & sent.HomeMessages 9+88 DirectoriasAb External connections* Starredijiminny-x-integrati..platform-inner-teamE) Channels# ai-chapter# alerts# backend# bugs# confusion-clinic# curiosity lab# engineering# general# jiminny-bg# platform-ticketsi product launches# random# releases# sofia-office# support# thank-yous# the people of jimi..ó- Direct messages(3) Aneliva Angelova....Stovan Tanev €Stefka Stoyanova(% Galya Dimitrova E1e. Aneliva Angelova0 Vasil VasilevJames GrahamNikolav Ivanova Inkas Kovali1 15 new messages XStatus: In DeyPrioritv:MCommentMore actions.Jira Cloua Arr 4:58 PM@Nikolay Ivanov transitioned a Story you are watching from Code Review — Ready for DeploymentJY-20/40 Kelease AJ Panorama reports to customersStatus: Keady for DeploymentN Type: StoryNI Assignee: Nikolay IvanovT Priority: MediumThursdav. April 30thvJira Cloud APP 11:43 AM@Nikolay Ivanov transitioned a Story you are watching from Ready for Deployment — DeployedJY-20740 Release AJ Panorama reports to customersCtatue. MonlovodNI Accionoo. Nitolov lvanoy1 Drioritu- ModiumJira Cloud APP 5:52 PM@Nikolay Ivanov transitioned a Bug you are watching from In Dev → Code ReviewJY-20699 Wrong formattine for summarv in the CRMStatus: Code Review• Tvne: BueNI Assienee: Nikolay Ivanov1 Prioritv: Medium@Nikolay Ivanov commented on a Bug you are watchingJY-20699 Wrong formatting for summary in the CRMRofaro ve AftorMondav. Mav 4th vJira Cloud APP 11:54 AM@Nikolay Ivanov transitioned a Bug vou are watchine from Code Review _ DeplovedJY-20699 Wrong formatting for summary in the CRMpawleeanhwa© Tvoe: BugNt Aecianos. Nitoley tuann1 Dinitr MadiomCommentMessage Jira Gloud•Annc+ Да95% 5• wea o May 20'30'34• • 0Q, Chat°= Cowork<> Coat+ New chat• Prolects8t Artifacts• customizeBulgarian citizenship application proces:Dawarich location tracking proiectViewing retention policy in screenpipeClean shot x video recording terminationHubSpot rate limit handling with executeUntitledScreen pipe. Is there ability…SMB mount access inconsistency betwe—What is the best switch can..Permiccion denied on screennine volumeScreenpipe sync database attachment eLast swimming outing with DaniDetinition of incarceratedChromecast remote volume buttons notSalesforce APl errors with OrganizationDaily activity summary from screenpipeMacBook unexpected restarts and kanjiSecurity patch review and testing guidarFood calorie values referenceTracking location historv from last weekScreennine WAL orocessing when stoorScreenpipe retention policy code location v3. Wipe local datarm -rf ~/.screenpipe/4. Clear npx cacherm -rf ~.npm/_npx5. Fresh startnpx screenpipealatest record --disable-audio --ignored-windows "Boosteroid" --retentioThat's it. Your NAS archive is untouched and the sync script will be re-created... wait, actually— vou just deleted ~/.screenpipe/ whichincludes screenpipe svnc.sh.Copv it out firstco ~ screenoine/screenoioe svnc.sh ~ screenoipe svnc.shDo that before sted 3. then after screenpide creates the fresh ~/. screenpipe/ directorv ornret run. move if back:mv ~/screenpipe sync.sh -/.screenpipe/screenpipe sync.shKeep going in Claude CodeSwitch to Claude Code and let Claude work directlv in vour reno.running and testing as it goes.Write a message…Open Claude CodeCannotAkyRelaunch to updatelK lukas. ProCiaudo ic Aland can make mictakes Plesco double-chock racnoncod...
|
26
|
NULL
|
NULL
|
NULL
|
|
31
|
4
|
2
|
2026-05-06T17:30:40.280803+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778088640280_m2.jpg...
|
iTerm2
|
NULL
|
True
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
ActivityFllesLaterJiminny... ~• Drafts & sent8 ActivityFllesLaterJiminny... ~• Drafts & sent88 DirectoriasAb External connections* Starrediijiminny-x-integrati..platform-inner-teamE) Channels# ai-chapter# alerts# backend# bugs# confusion-clinic# curiosity lab# engineering# general# jiminny-bg# platform-ticketsi product launches# random# releases# sofia-office# support# thank-yous# the people of jimi..ó- Direct messages(3) Aneliva Angelova....Stovan Tanev €Stefka Stoyanova(% Galya Dimitrova E1e. Aneliva Angelova0 Vasil VasilevJames GrahamNikolav Ivanova Inkas Kovali•AnncQ Describe what you are lookingJhra cloudHomeMessages 9+1 15 new messages XStatus: In DeyPrioritv:MCommentMore actions.Jira Cloua Arr 4:58 PM@Nikolay Ivanov transitioned a Story you are watching from Code Review → Ready for DeploymentJY-20/40 Kelease AJ Panorama reports to customersStatus: Keady for DeploymentN Type: StoryNI Assignee: Nikolay IvanovT Priority: MediumThursdav. April 30thvJira Cloud APP 11:43 AM@Nikolay Ivanov transitioned a Story you are watching from Ready for Deployment — DeployedJY-20740 Release AJ Panorama reports to customersCtatue. MonlovodNI Accionoo. Nitolov lvanoy1 Drioritu- ModiumJira Cloud APP 5:52 PM@Nikolay Ivanov transitioned a Bug you are watching from In Dev → Code ReviewJY-20699 Wrong formattine for summarv in the CRMStatus: Code Review• Tvne: BueNI Assienee: Nikolav Ivanov1 Prioritv: Medium@Nikolay Ivanov commented on a Bug you are watchingJY-20699 Wrong formatting for summary in the CRMRofaro ve AftorMondav. Mav 4th vJira Cloud APP 11:54 AM@Nikolay Ivanov transitioned a Bug vou are watchine from Code Review _ DeplovedJY-20699 Wrong formatting for summary in the CRMpaweeanawih© Tvoe: BugNt Aecianos. Nitoley tuann1 Dinitr MadiomCommentMessage Jira Gloud+ Да( Pull requests • screenpipe/screenpipe • GitHubHostinger loain I Sian in to Hostinger account@ Login - Nginx Proxy ManagerScreenpipe — Archive(*SQLite Web: archive.db( SQLite Web: db.salitescreenpipe/.claude/skills at main • screenpipe/scre X- New Tab• github.com/screenpipe/screenpipe• Goocle Geminilreview the reoo nitos:github.com/screenpipe/screenpipe and tind where is theretention policy codeGShow thinkingIseem to be encountering an error. Can I trysomething else for you?can you read the repoGShow thinkingsorry, something went wrong. Please try yourrequest again.Ask GeminiPro vGemini is Al and can make mistakes, including about people.Your privacy and Gemin,Summarize pagewea o May 20:30.44sian in@ screenpipe / screenpipe (Public)<> Code• Issues 1387 Pull requests 16Discussions• Actions{ main IGo to file• Codelouis030195 Bump app to v2.4.145, Bump CLI to v0.3.316 - .Soezzea• 2 hours ago.cargcci: enable prebuilt NASM objects for Win..2 months ago.claude/skillschore(mcp: upaate worktiow + aocs to n..last weekdevcontainerFix devcontainer cargo path (#3214)2 days agoD.githubci: wire frontend tests + biome lint + lefth...5 days ago^ apps/screenpipe-app-tauriBumo apo to v2.4.145. Bumo CLl to v0.3.....Zhours agocratesBump app to v2.4.145, Bump CLI to v0.3....2 hours agedocker/linux-testBump app to v2.0.5783 months ago1 docschandelod: week of mav 3. 2026 (#3746)3hours ado• eechore: cargo fmt across all crateslast monthpackadestixlal-qarewav: sanitize toouse.ld 1o m...Znours adoView all filesL README@ Code of conduct82 Contributinal88 Licenco[ screenpipe ]Al memory for vour screen...
|
NULL
|
-6177731450564651884
|
NULL
|
click
|
ocr
|
NULL
|
ActivityFllesLaterJiminny... ~• Drafts & sent8 ActivityFllesLaterJiminny... ~• Drafts & sent88 DirectoriasAb External connections* Starrediijiminny-x-integrati..platform-inner-teamE) Channels# ai-chapter# alerts# backend# bugs# confusion-clinic# curiosity lab# engineering# general# jiminny-bg# platform-ticketsi product launches# random# releases# sofia-office# support# thank-yous# the people of jimi..ó- Direct messages(3) Aneliva Angelova....Stovan Tanev €Stefka Stoyanova(% Galya Dimitrova E1e. Aneliva Angelova0 Vasil VasilevJames GrahamNikolav Ivanova Inkas Kovali•AnncQ Describe what you are lookingJhra cloudHomeMessages 9+1 15 new messages XStatus: In DeyPrioritv:MCommentMore actions.Jira Cloua Arr 4:58 PM@Nikolay Ivanov transitioned a Story you are watching from Code Review → Ready for DeploymentJY-20/40 Kelease AJ Panorama reports to customersStatus: Keady for DeploymentN Type: StoryNI Assignee: Nikolay IvanovT Priority: MediumThursdav. April 30thvJira Cloud APP 11:43 AM@Nikolay Ivanov transitioned a Story you are watching from Ready for Deployment — DeployedJY-20740 Release AJ Panorama reports to customersCtatue. MonlovodNI Accionoo. Nitolov lvanoy1 Drioritu- ModiumJira Cloud APP 5:52 PM@Nikolay Ivanov transitioned a Bug you are watching from In Dev → Code ReviewJY-20699 Wrong formattine for summarv in the CRMStatus: Code Review• Tvne: BueNI Assienee: Nikolav Ivanov1 Prioritv: Medium@Nikolay Ivanov commented on a Bug you are watchingJY-20699 Wrong formatting for summary in the CRMRofaro ve AftorMondav. Mav 4th vJira Cloud APP 11:54 AM@Nikolay Ivanov transitioned a Bug vou are watchine from Code Review _ DeplovedJY-20699 Wrong formatting for summary in the CRMpaweeanawih© Tvoe: BugNt Aecianos. Nitoley tuann1 Dinitr MadiomCommentMessage Jira Gloud+ Да( Pull requests • screenpipe/screenpipe • GitHubHostinger loain I Sian in to Hostinger account@ Login - Nginx Proxy ManagerScreenpipe — Archive(*SQLite Web: archive.db( SQLite Web: db.salitescreenpipe/.claude/skills at main • screenpipe/scre X- New Tab• github.com/screenpipe/screenpipe• Goocle Geminilreview the reoo nitos:github.com/screenpipe/screenpipe and tind where is theretention policy codeGShow thinkingIseem to be encountering an error. Can I trysomething else for you?can you read the repoGShow thinkingsorry, something went wrong. Please try yourrequest again.Ask GeminiPro vGemini is Al and can make mistakes, including about people.Your privacy and Gemin,Summarize pagewea o May 20:30.44sian in@ screenpipe / screenpipe (Public)<> Code• Issues 1387 Pull requests 16Discussions• Actions{ main IGo to file• Codelouis030195 Bump app to v2.4.145, Bump CLI to v0.3.316 - .Soezzea• 2 hours ago.cargcci: enable prebuilt NASM objects for Win..2 months ago.claude/skillschore(mcp: upaate worktiow + aocs to n..last weekdevcontainerFix devcontainer cargo path (#3214)2 days agoD.githubci: wire frontend tests + biome lint + lefth...5 days ago^ apps/screenpipe-app-tauriBumo apo to v2.4.145. Bumo CLl to v0.3.....Zhours agocratesBump app to v2.4.145, Bump CLI to v0.3....2 hours agedocker/linux-testBump app to v2.0.5783 months ago1 docschandelod: week of mav 3. 2026 (#3746)3hours ado• eechore: cargo fmt across all crateslast monthpackadestixlal-qarewav: sanitize toouse.ld 1o m...Znours adoView all filesL README@ Code of conduct82 Contributinal88 Licenco[ screenpipe ]Al memory for vour screen...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
33
|
4
|
3
|
2026-05-06T17:30:45.543196+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778088645543_m2.jpg...
|
iTerm2
|
NULL
|
True
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
DMSActivityLateJiminny ... v• Drafts & sent88 DMSActivityLateJiminny ... v• Drafts & sent88 DirectoriasAb External connections* Starredijiminny-x-integrati..platform-inner-team#) Channels# ai-chapter# alerts# backend# bugs# confusion-clinic# curiosity lab# engineering# general# jiminny-bg# platform-ticketsi product launches# random# releases# sofia-office# support# thank-yous# the people of jimi..A Direct meccagpç(3) Aneliva Angelova....Stovan Tanev €Stefka StoyanovaVes.(% Galya Dimitrova E1e. Aneliva Angelova0 Vasil VasilevJames GrahamNikolav Ivanova Inkas Kovali•Annc@ Describe what you are looking forJira CloudHomeMessages 9+Status: In DeyNI Assinee: Nikolay Ivanov1 Prioritv: NCommentMore actions.Jira Cloua Arr 4:58 PM@Nikolay Ivanov transitioned a Story you are watching from Code RevJY-20/40 Kelease AJ Panorama reports to customersStatus: Keady for DeploymentN Type: StoryNI Assignee: Nikolay IvanovPull requests • screenpipe/screenpipe • GitHubHostinger loain I Sian in to Hostinger account@ Login - Nginx Proxy ManagerScreenpipe - Archive* soLito Wep: archive.dbSQLite Web: db.sqlitescreenoioel.claude/skilis at main - screenoioe/scre- New TabJira Cloud APP 11:43 AM@Nikolay Ivanov transitioned a Story you are watching from Ready foJY-20740 Release AJ Panorama reports to customersCtatue. MonlovodNI Accionoo- Nilolov Ivanoy1 Drioritv. MoJira Cloud APP 5:52 PM@Nikolav Ivanov transitioned a Bug vou are watching from Tn Dev —JY-20699 Wrong formatting for summary in the CRMStatus: Code Review• Tvne: BueNI Assienee: Nikolay Ivanov1 Prioritv: N@Nikolay Ivanov commented on a Bug you are watchingJY-20699 Wrong formatting for summary in the CRMRofaro ve AftorJira Cloud APP 11:54 AM@Nikolay Ivanov transitioned a Bug vou are watchine from Code Revi.JY-20699 Wrong formatting for summary in the CRMpaweeanawih© Tvoe: BugNt Aecianos. Nitoley tuann1 Diniho ModCommentMessage Jira Gloud+ Аagithub.com/screenpipe/screenpipePlatform v Solutions v ResourcesOpen SourceEnterprisevPricing= screenpipe / screenpipe Publ‹ Code102.18 2: rchive.db• Issues 13? Pull requestsDiscuscions• Actions• Projects© Security and quality~ Insights} main +99 517 Branches • 383 Tags• Go to file• Code*0S louis030195 Bump app to v2.4.145, Bump CLI to v0.3.316 - feat(connecti...3be22ea • 2 hours ago.cargo.claude/skillsdevcontainergithubapps/screenpipe-app-taurcratesdocker/linux-testdocsW eepackagesscrints1 .gitattributes(9 aitianore(9 CL AUDE md1' CODE OF CONDUCT.md(9 CONTRIBUTING.mdl[ Cargo.lock19 Carao toml! DESIGN.md19 LICENSE.md(9 READMF_ia.mdlU 8,790 Commitsci: enable prebuilt NASM objects for Windows Clchore mco: uodare workriow + cocs lo new packaces/Scl...Fix devcontainer carao oath :3214)ci: wire frontend tests + biome lint + lefthook + bump wind...Bump app to v2.4.145. Bump CLI to 0.3.316 - feat(conne...Bump app to v2.4.145, Bump CLI to v0.3.316 - feat(conne...Bump app to v2.0.578changeloa: week of mav 3. 2026 (#3246chore: cargo fmt across all cratesfix(ai-qatewav): sanitize tool use.id to match Anthropic ^[...fix: enrich OpenAPl spec with tags, summaries, and descri...fix: download mix.metallib from GitHub releases instead of...fix(drm): pause capture for Omnissa/VMware Horizon Clie…Update CLAUDE.md (#3108)Create CODE OF CONDUCT.mdfix: Windows prebuild 7z resolution and simplify CONTRIB...Bump app to v2.4.145. Bump CLI to v0.3.316 - feat(conne...Bumo apo to v2.4,145. Bumo CLI to v0.3.316 — feat(conne…cleanunadd eel enterprise edition with proprietary licensechore men): undate workflow + docs to new nackages/scr..2 months aaolast week2 days ago5 days ago2 hours ago2 hours ago2 months ago3 hours aaolast month2 hours agolast month2 months ago3 weeks adolast weekmonins ado2 months ago2 hours ago2 hours aao2 months agoZ months agowea o May 20.30.4/Sign up# Star 18.6k• Search or jump to..NotificationsAboutRun agents that work based on whatvou do. 24/7 local screen & micrecording for the superintelligenceera©screenpi.pe•I Readmed View licenseCode of conduct* ContributinalActivity= Custom oronerties* 18.6k stars• 104 watching|9 1.7k forksReport repositoryReleases 320• Screenpipe App v2.4.144Z hours ago+ 319 releasesContributors 114Sign in* Fork 1.7k+ 100 contrioutors...
|
NULL
|
-625900905823381842
|
NULL
|
visual_change
|
ocr
|
NULL
|
DMSActivityLateJiminny ... v• Drafts & sent88 DMSActivityLateJiminny ... v• Drafts & sent88 DirectoriasAb External connections* Starredijiminny-x-integrati..platform-inner-team#) Channels# ai-chapter# alerts# backend# bugs# confusion-clinic# curiosity lab# engineering# general# jiminny-bg# platform-ticketsi product launches# random# releases# sofia-office# support# thank-yous# the people of jimi..A Direct meccagpç(3) Aneliva Angelova....Stovan Tanev €Stefka StoyanovaVes.(% Galya Dimitrova E1e. Aneliva Angelova0 Vasil VasilevJames GrahamNikolav Ivanova Inkas Kovali•Annc@ Describe what you are looking forJira CloudHomeMessages 9+Status: In DeyNI Assinee: Nikolay Ivanov1 Prioritv: NCommentMore actions.Jira Cloua Arr 4:58 PM@Nikolay Ivanov transitioned a Story you are watching from Code RevJY-20/40 Kelease AJ Panorama reports to customersStatus: Keady for DeploymentN Type: StoryNI Assignee: Nikolay IvanovPull requests • screenpipe/screenpipe • GitHubHostinger loain I Sian in to Hostinger account@ Login - Nginx Proxy ManagerScreenpipe - Archive* soLito Wep: archive.dbSQLite Web: db.sqlitescreenoioel.claude/skilis at main - screenoioe/scre- New TabJira Cloud APP 11:43 AM@Nikolay Ivanov transitioned a Story you are watching from Ready foJY-20740 Release AJ Panorama reports to customersCtatue. MonlovodNI Accionoo- Nilolov Ivanoy1 Drioritv. MoJira Cloud APP 5:52 PM@Nikolav Ivanov transitioned a Bug vou are watching from Tn Dev —JY-20699 Wrong formatting for summary in the CRMStatus: Code Review• Tvne: BueNI Assienee: Nikolay Ivanov1 Prioritv: N@Nikolay Ivanov commented on a Bug you are watchingJY-20699 Wrong formatting for summary in the CRMRofaro ve AftorJira Cloud APP 11:54 AM@Nikolay Ivanov transitioned a Bug vou are watchine from Code Revi.JY-20699 Wrong formatting for summary in the CRMpaweeanawih© Tvoe: BugNt Aecianos. Nitoley tuann1 Diniho ModCommentMessage Jira Gloud+ Аagithub.com/screenpipe/screenpipePlatform v Solutions v ResourcesOpen SourceEnterprisevPricing= screenpipe / screenpipe Publ‹ Code102.18 2: rchive.db• Issues 13? Pull requestsDiscuscions• Actions• Projects© Security and quality~ Insights} main +99 517 Branches • 383 Tags• Go to file• Code*0S louis030195 Bump app to v2.4.145, Bump CLI to v0.3.316 - feat(connecti...3be22ea • 2 hours ago.cargo.claude/skillsdevcontainergithubapps/screenpipe-app-taurcratesdocker/linux-testdocsW eepackagesscrints1 .gitattributes(9 aitianore(9 CL AUDE md1' CODE OF CONDUCT.md(9 CONTRIBUTING.mdl[ Cargo.lock19 Carao toml! DESIGN.md19 LICENSE.md(9 READMF_ia.mdlU 8,790 Commitsci: enable prebuilt NASM objects for Windows Clchore mco: uodare workriow + cocs lo new packaces/Scl...Fix devcontainer carao oath :3214)ci: wire frontend tests + biome lint + lefthook + bump wind...Bump app to v2.4.145. Bump CLI to 0.3.316 - feat(conne...Bump app to v2.4.145, Bump CLI to v0.3.316 - feat(conne...Bump app to v2.0.578changeloa: week of mav 3. 2026 (#3246chore: cargo fmt across all cratesfix(ai-qatewav): sanitize tool use.id to match Anthropic ^[...fix: enrich OpenAPl spec with tags, summaries, and descri...fix: download mix.metallib from GitHub releases instead of...fix(drm): pause capture for Omnissa/VMware Horizon Clie…Update CLAUDE.md (#3108)Create CODE OF CONDUCT.mdfix: Windows prebuild 7z resolution and simplify CONTRIB...Bump app to v2.4.145. Bump CLI to v0.3.316 - feat(conne...Bumo apo to v2.4,145. Bumo CLI to v0.3.316 — feat(conne…cleanunadd eel enterprise edition with proprietary licensechore men): undate workflow + docs to new nackages/scr..2 months aaolast week2 days ago5 days ago2 hours ago2 hours ago2 months ago3 hours aaolast month2 hours agolast month2 months ago3 weeks adolast weekmonins ado2 months ago2 hours ago2 hours aao2 months agoZ months agowea o May 20.30.4/Sign up# Star 18.6k• Search or jump to..NotificationsAboutRun agents that work based on whatvou do. 24/7 local screen & micrecording for the superintelligenceera©screenpi.pe•I Readmed View licenseCode of conduct* ContributinalActivity= Custom oronerties* 18.6k stars• 104 watching|9 1.7k forksReport repositoryReleases 320• Screenpipe App v2.4.144Z hours ago+ 319 releasesContributors 114Sign in* Fork 1.7k+ 100 contrioutors...
|
31
|
NULL
|
NULL
|
NULL
|
|
35
|
4
|
4
|
2026-05-06T17:30:49.964395+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778088649964_m2.jpg...
|
iTerm2
|
NULL
|
True
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
ActivityJiminny ... v• Drafts & sent8 Director ActivityJiminny ... v• Drafts & sent8 DirectoriesA External connections* Starredii& jiminny-x-integrati...platform-inner-team® Channels# ai-chapter# alerts# backend# bugs# confusion-clinic# curiosity_lab# engineering# general# jiminny-bg# platform-ticketsi product launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi...^ Direct messagesB Aneliya Angelova, ...Stovan Tanev €. Stefka Stoyanovaf. VesP. Galya DimitrovaAº. Aneliya AngelovaB. Vasil Vasilevdo James GrahamNikolav IvanovInkas Kovali•Annc@ Describe what you are looking forJira CloudHomeMessages 9+Status: In DeyNI Assignee: Nikolay IvanovT Priority: MCommentMore actions...Jira Cloua Arr 4:58 PM@Nikolay Ivanov transitioned a Story you are watching from Code RevJY-20/40 Kelease AJ Panorama reports to customersStatus: Keady for DeploymentTурe: StoryNI Assignee: Nikolay Ivanov→ XPull requests • screenpipe/screenpipe • GitHubH Hostinger login | Sign in to Hostinger accountLogin - Nginx Proxy Manager* Screenpipe - Archive® SQLite Web: archive.dbSQLite Web: db.sqliteo) screenoioel claude/skilis at main • screenoioe/screeno)- New TabJira Cloud APP 11:43 AM4 @Nikolay Ivanov transitioned a Story you are watching from Ready foJY-20740 Release AJ Panorama reports to customersCtatue. MonlovodNI Assignee: Nikolay Ivanov1 Priority: MelJira Cloud APP 5:52 PM@Nikolav Ivanov transitioned a Bug vou are watching from Tn Dev —JY-20699 Wrong formatting for summarv in the CRMStatus: Code Review• Type: BugNI Assienee: Nikolav Ivanov1 Prioritv: N@Nikolay Ivanov commented on a Bug you are watchingJY-20699 Wrong formatting for summary in the CRMBefore vs AfterJira Cloud APP 11:54 AM# @Nikolay Ivanov transitioned a Bug you are watching from Code ReviJY-20699 Wrong formatting for summary in the CRMpawleeanhwa• Type: BugNI Assignee: Nikolay IvanovT Priority: MedlCommentMessage Jira Cloud+ Aa@Not Securehttp://[IP_ADDRESS]:8768/audio_transcriptions/sqlite-web 0.7.2db.sqlite audio_transcriptionstable name..seix-giduotsaudio_chunksaudio_tagsaudio_transcrirlonsaudio transcriptions fts (V)audio_transcriptions_.audio_transcriptions_.dualo ranscriptions.elementselements_fts (v)elements_fts_configelements_fts_dataelements fts idxlframesframes_fts (v)frames_fts_configframes_fts_dataTrames Tis 1oxmeetingsmemoriesmemories_fts (v)memories iis contialmemories_fts_datamemories tts 1dxocr_textpipe_executionspipe_scheduler_statesecretsspeaker_embeddingsspeakerssqlite_sequencesalite stat1lsqlite_stat4tagsui eventsui_events_fts (v)ul events tts contialui_events_fts_datastructureContentQueryExporiSQLCREATE TABLE "audio transcrintions"id INTEGER PRIMARY KEY AUTOINCREMENT,audio_chunk_id INTEGERNULL,OTTSEt1ndex INItotk NoI NULL,timestamo TIMESTAMPNOT NULL,transcription TEXT NOT NULL,device TEXTDEFAULTis input device BOOLEAN NOT NULL DEFAULT TRUE,speaker_id INTEGER,stare tipe on engine TEXT NOT MULL DEFAULT "wnisper',start_timeend time REAL,text_length INTEGER,synced_at DATETIME,FOREIGN KEY (audio_chunk_id) REFERENCES audio_chunks(id)ColumnsColumnaudio_chunk_idoftset indextimestamoltranscriotiondeviceis 1nput devicespeaker_idtranscrintion enainestart_timeend timetext lenathsync_idData typeINTEGERINTEGERINTEGERTIMESTAMPTEXTITEXTBOOLEANINTEGERTEXTREALREALINTEGERITEXTAllow null* 95% L2 * Wedo May 20:50:01Primary keyActionsread-onlyread-onlyread-onlyread-onlyread-onlyread-onlyread-onlyread-onlyread-onlyread-onlyread-onlyread-onlyread-only...
|
NULL
|
-9200357565485790993
|
NULL
|
visual_change
|
ocr
|
NULL
|
ActivityJiminny ... v• Drafts & sent8 Director ActivityJiminny ... v• Drafts & sent8 DirectoriesA External connections* Starredii& jiminny-x-integrati...platform-inner-team® Channels# ai-chapter# alerts# backend# bugs# confusion-clinic# curiosity_lab# engineering# general# jiminny-bg# platform-ticketsi product launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi...^ Direct messagesB Aneliya Angelova, ...Stovan Tanev €. Stefka Stoyanovaf. VesP. Galya DimitrovaAº. Aneliya AngelovaB. Vasil Vasilevdo James GrahamNikolav IvanovInkas Kovali•Annc@ Describe what you are looking forJira CloudHomeMessages 9+Status: In DeyNI Assignee: Nikolay IvanovT Priority: MCommentMore actions...Jira Cloua Arr 4:58 PM@Nikolay Ivanov transitioned a Story you are watching from Code RevJY-20/40 Kelease AJ Panorama reports to customersStatus: Keady for DeploymentTурe: StoryNI Assignee: Nikolay Ivanov→ XPull requests • screenpipe/screenpipe • GitHubH Hostinger login | Sign in to Hostinger accountLogin - Nginx Proxy Manager* Screenpipe - Archive® SQLite Web: archive.dbSQLite Web: db.sqliteo) screenoioel claude/skilis at main • screenoioe/screeno)- New TabJira Cloud APP 11:43 AM4 @Nikolay Ivanov transitioned a Story you are watching from Ready foJY-20740 Release AJ Panorama reports to customersCtatue. MonlovodNI Assignee: Nikolay Ivanov1 Priority: MelJira Cloud APP 5:52 PM@Nikolav Ivanov transitioned a Bug vou are watching from Tn Dev —JY-20699 Wrong formatting for summarv in the CRMStatus: Code Review• Type: BugNI Assienee: Nikolav Ivanov1 Prioritv: N@Nikolay Ivanov commented on a Bug you are watchingJY-20699 Wrong formatting for summary in the CRMBefore vs AfterJira Cloud APP 11:54 AM# @Nikolay Ivanov transitioned a Bug you are watching from Code ReviJY-20699 Wrong formatting for summary in the CRMpawleeanhwa• Type: BugNI Assignee: Nikolay IvanovT Priority: MedlCommentMessage Jira Cloud+ Aa@Not Securehttp://[IP_ADDRESS]:8768/audio_transcriptions/sqlite-web 0.7.2db.sqlite audio_transcriptionstable name..seix-giduotsaudio_chunksaudio_tagsaudio_transcrirlonsaudio transcriptions fts (V)audio_transcriptions_.audio_transcriptions_.dualo ranscriptions.elementselements_fts (v)elements_fts_configelements_fts_dataelements fts idxlframesframes_fts (v)frames_fts_configframes_fts_dataTrames Tis 1oxmeetingsmemoriesmemories_fts (v)memories iis contialmemories_fts_datamemories tts 1dxocr_textpipe_executionspipe_scheduler_statesecretsspeaker_embeddingsspeakerssqlite_sequencesalite stat1lsqlite_stat4tagsui eventsui_events_fts (v)ul events tts contialui_events_fts_datastructureContentQueryExporiSQLCREATE TABLE "audio transcrintions"id INTEGER PRIMARY KEY AUTOINCREMENT,audio_chunk_id INTEGERNULL,OTTSEt1ndex INItotk NoI NULL,timestamo TIMESTAMPNOT NULL,transcription TEXT NOT NULL,device TEXTDEFAULTis input device BOOLEAN NOT NULL DEFAULT TRUE,speaker_id INTEGER,stare tipe on engine TEXT NOT MULL DEFAULT "wnisper',start_timeend time REAL,text_length INTEGER,synced_at DATETIME,FOREIGN KEY (audio_chunk_id) REFERENCES audio_chunks(id)ColumnsColumnaudio_chunk_idoftset indextimestamoltranscriotiondeviceis 1nput devicespeaker_idtranscrintion enainestart_timeend timetext lenathsync_idData typeINTEGERINTEGERINTEGERTIMESTAMPTEXTITEXTBOOLEANINTEGERTEXTREALREALINTEGERITEXTAllow null* 95% L2 * Wedo May 20:50:01Primary keyActionsread-onlyread-onlyread-onlyread-onlyread-onlyread-onlyread-onlyread-onlyread-onlyread-onlyread-onlyread-onlyread-only...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
38
|
4
|
5
|
2026-05-06T17:30:57.626110+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778088657626_m2.jpg...
|
iTerm2
|
NULL
|
True
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
ActivityJiminny ... v• Drafts & sent88 Directo ActivityJiminny ... v• Drafts & sent88 DirectoriasAb External connections* Starredijiminny-x-integrati..platform-inner-team#) Channels# ai-chapter# alerts# backend# bugs# confusion-clinic# curiosity lab# engineering# general# jiminny-bg# platform-ticketsi product launches# random# releases# sofia-office# support# thank-yous# the people of jimi..A Direct meccagpç(3) Aneliva Angelova....Stovan Tanev €Stefka StoyanovaVes.(% Galya Dimitrova E1e. Aneliva Angelova0 Vasil VasilevJames GrahamNikolav Ivanova Inkas Kovali•Annc@ Describe what you are looking forJira CloudHomeMessages 9+Status: In DeyNI Assinee: Nikolay Ivanov1 Prioritv: NCommentMore actions.Jira Cloua Arr 4:58 PM@Nikolay Ivanov transitioned a Story you are watching from Code RevJY-20/40 Kelease AJ Panorama reports to customersStatus: Keady for DeploymentN Type: StoryNI Assignee: Nikolay IvanovPull requests • screenpipe/screenpipe • GitHubHostinger loain I Sian in to Hostinger accoun:@ Login - Nginx Proxy ManagerScreenpipe - Archive( SQLite Web: archive.dbSQLite Web: db.sqliteo) screenoioel claude/skilis at main • screenoioe/screeno)- New TabJira Cloud APP 11:43 AM@Nikolay Ivanov transitioned a Story you are watching from Ready foJY-20740 Release AJ Panorama reports to customersCtatue. MonlovodNI Accionoo- Nilolov Ivanoy1 Drioritv. MoJira Cloud APP 5:52 PM@Nikolav Ivanov transitioned a Bug vou are watching from Tn Dev —JY-20699 Wrong formatting for summarv in the CRMStatus: Code Review• Tvne: BueNI Assienee: Nikolay Ivanov1 Prioritv: N@Nikolay Ivanov commented on a Bug you are watchingJY-20699 Wrong formatting for summary in the CRMRofaro ve AftorJira Cloud APP 11:54 AM@Nikolay Ivanov transitioned a Bug vou are watchine from Code Revi.JY-20699 Wrong formatting for summary in the CRMpaweeanawih© Tvoe: BugNt Aecianos. Nitoley tuann1 Diniho ModCommentMessage Jira Gloud+ ДаNot Securehttp://[IP_ADDRESS]:8768/audio_transcriptions/contentsqlite-web 0.7.2db.sqlite audio_transcriptions 49 rows, showing page 1_sqlx_migrationsaudio chunksiaudio_tagsaudio transcriotions fts (v)audio_transcriptions_audio_transcriptions_.dualo ranscriptions.elementselements_fts (v)elements_fts_configelements_fts_dataelements fts idxTramesframes_fts (v)Trames mis contloframes fts dataTrames Tis 1oxmeetingsmemoriesmemories_fts (v)memories iis contialmemories_fts_datamemories tts 1dxOCr.Textpipe_executionspipe_scheduler_statesecretsspeaker_embeddingsspeakerssalle sequencesalite stat1lsalite stat4ui eventsui evente ftc (v)ul events tts contialstructurecontentQuervExporiidaudio chunk_id offset index timestamp2 259 10110 991111413:12914 :132115 13216 | 135 |17 13518 | 138119 138 |120 140121 15222 | 15323 155155|25:15826:15827 176transcription2026-04-09T16:53:20+00:00 | do for you. Run the creditcheck. Deal apartment …2026-04-09T16:59:22+00:00 Class is technically…2026-04-0911/:02-52+00:002026-04-18T10:34:24÷00:00 | should.2026-04-18T10:34:24+00:00 can't wait to see you again2026-04-18T10:34:56+00:00 Bye2026-04-18110:34:56÷00:00 : Thank vou.2026-04-18T10:35:26+00:00 Thank you2026-04-18T10:36:26+00:00 See you.2026-04-18T10:35:56÷00:001the category of the C, then we'lltake a resol .2026-04-18110:39:15÷00:00One of the things I love aboutnaving this projec2026-04-18T10:39:37+00:00 your orchestrating now. Eventhough you might not …2026-04-18T10:42:24÷00:00 : more information nleasesubscribe to the channel.2026-04-18T10:42:54÷00:00 Good. Goodi2026-04-18T10:42:54+00:00 You want some?2026-04-18T10:43:40+00:00 Thanks for watching!2026-04-18T10:43:40+00:00 I'Il actually look back down.2026-04-18T10:44.25+00:00lust some Euro or aorchestrating now. Even thoug2026-04-18T10:44:25÷00:00 That's alli2026-04-18T10:44:47+00:00 Thank you.2026-04-18T10:47:22+00:00 Not a dog2026-04-18T10:47:22+00:00 More to go2026-04-18T10:47:52+00:00 Thank you.2026-04-18T10:47:52+00:00 So, this is our, this is the real,2026-04-18T10:48:22÷00:00 tvne ofl2026-04-18T10:48:22÷00:001ohone2026-04-18T10:52:21+00:00 Okay. Thanks for watchingdevicesystem AudioSystem Audiosystem AudiosoundcoreAeroclipsounacoreAeroClipounacotoAeroClipsoundcoreAeroClipsoundcoreAeroClinAeroCliosoundcoreAeroClipSvstem Audiolsystem AudiosoundcoreAeroClipsoundcoreAeroClinSystem Audiosystem AudioSystem AudioSvstem AudiolSvstem AudiolAeroClipsoundcoreAeroClipsoundcoreAoroClinsoundcoreAeroClipAerocllpsounacoreis inpur device speaker ld transcription engine Start timelFalseralseFalseTrueTrueTruelTruelTrueTrueTrueFalseFalseTrueTrueTrueFalseralseFalseFalselFalseTrueTrueTrueE TruelTrueWhisperlinvwhisperlinyWhisperlinyWhisperTinywhisperlinyWhisperlinyWhisperTinyWhisperTinyWhisperlinyWhisperTinyWhisperTinyWhisperTinyWhisperTinyWhisperTinyWhisperTinyWhisperTinyWhisperlinyWhisperTinyWhisoerTinyWhisnerTinvWhisperTinyWhisperTinyWhisperTinyWhisperTinyWhisnerTinvWhisoerTinyWhisperTinyendtimetext_length sync_id synced_at30.01630.01630.01626.0325625| 26.4375625 |1028.4794375 29.8631875 2824.5138125 24. .01622.0669375 24.1594[PHONE]6.8088125 29.8631[PHONE]625 8.786312513023.5856875 29.8631875 5018.1013125 |19.3163125 |1220.7844375 28.1756875 1520.3119375 27.6188125 2127.9394375 29.5931875 3012.7350625 18.6413125 7928.7325625 | 29.6269[PHONE]875 |1.833812525.5263125 26.1675625 1128.2600625 28800062522.3200625 23.7375625 1124.2775625 29. .1931875 25.9144375 27NULLNULUNULLINULLNULIINULLINULLNULLNULLINULLNULINULLINULLINULLNULLINULLINULLINULITNuL INULLNUTTTNULINULLNULLNULLNULLTNULLNULLNULLNULLNULTTNULLINULLNULLNULUNULLTNULLNULLNULLNULLNULITNULLNULTNULLINULLNULLNULL...
|
NULL
|
-4491996253482823225
|
NULL
|
visual_change
|
ocr
|
NULL
|
ActivityJiminny ... v• Drafts & sent88 Directo ActivityJiminny ... v• Drafts & sent88 DirectoriasAb External connections* Starredijiminny-x-integrati..platform-inner-team#) Channels# ai-chapter# alerts# backend# bugs# confusion-clinic# curiosity lab# engineering# general# jiminny-bg# platform-ticketsi product launches# random# releases# sofia-office# support# thank-yous# the people of jimi..A Direct meccagpç(3) Aneliva Angelova....Stovan Tanev €Stefka StoyanovaVes.(% Galya Dimitrova E1e. Aneliva Angelova0 Vasil VasilevJames GrahamNikolav Ivanova Inkas Kovali•Annc@ Describe what you are looking forJira CloudHomeMessages 9+Status: In DeyNI Assinee: Nikolay Ivanov1 Prioritv: NCommentMore actions.Jira Cloua Arr 4:58 PM@Nikolay Ivanov transitioned a Story you are watching from Code RevJY-20/40 Kelease AJ Panorama reports to customersStatus: Keady for DeploymentN Type: StoryNI Assignee: Nikolay IvanovPull requests • screenpipe/screenpipe • GitHubHostinger loain I Sian in to Hostinger accoun:@ Login - Nginx Proxy ManagerScreenpipe - Archive( SQLite Web: archive.dbSQLite Web: db.sqliteo) screenoioel claude/skilis at main • screenoioe/screeno)- New TabJira Cloud APP 11:43 AM@Nikolay Ivanov transitioned a Story you are watching from Ready foJY-20740 Release AJ Panorama reports to customersCtatue. MonlovodNI Accionoo- Nilolov Ivanoy1 Drioritv. MoJira Cloud APP 5:52 PM@Nikolav Ivanov transitioned a Bug vou are watching from Tn Dev —JY-20699 Wrong formatting for summarv in the CRMStatus: Code Review• Tvne: BueNI Assienee: Nikolay Ivanov1 Prioritv: N@Nikolay Ivanov commented on a Bug you are watchingJY-20699 Wrong formatting for summary in the CRMRofaro ve AftorJira Cloud APP 11:54 AM@Nikolay Ivanov transitioned a Bug vou are watchine from Code Revi.JY-20699 Wrong formatting for summary in the CRMpaweeanawih© Tvoe: BugNt Aecianos. Nitoley tuann1 Diniho ModCommentMessage Jira Gloud+ ДаNot Securehttp://[IP_ADDRESS]:8768/audio_transcriptions/contentsqlite-web 0.7.2db.sqlite audio_transcriptions 49 rows, showing page 1_sqlx_migrationsaudio chunksiaudio_tagsaudio transcriotions fts (v)audio_transcriptions_audio_transcriptions_.dualo ranscriptions.elementselements_fts (v)elements_fts_configelements_fts_dataelements fts idxTramesframes_fts (v)Trames mis contloframes fts dataTrames Tis 1oxmeetingsmemoriesmemories_fts (v)memories iis contialmemories_fts_datamemories tts 1dxOCr.Textpipe_executionspipe_scheduler_statesecretsspeaker_embeddingsspeakerssalle sequencesalite stat1lsalite stat4ui eventsui evente ftc (v)ul events tts contialstructurecontentQuervExporiidaudio chunk_id offset index timestamp2 259 10110 991111413:12914 :132115 13216 | 135 |17 13518 | 138119 138 |120 140121 15222 | 15323 155155|25:15826:15827 176transcription2026-04-09T16:53:20+00:00 | do for you. Run the creditcheck. Deal apartment …2026-04-09T16:59:22+00:00 Class is technically…2026-04-0911/:02-52+00:002026-04-18T10:34:24÷00:00 | should.2026-04-18T10:34:24+00:00 can't wait to see you again2026-04-18T10:34:56+00:00 Bye2026-04-18110:34:56÷00:00 : Thank vou.2026-04-18T10:35:26+00:00 Thank you2026-04-18T10:36:26+00:00 See you.2026-04-18T10:35:56÷00:001the category of the C, then we'lltake a resol .2026-04-18110:39:15÷00:00One of the things I love aboutnaving this projec2026-04-18T10:39:37+00:00 your orchestrating now. Eventhough you might not …2026-04-18T10:42:24÷00:00 : more information nleasesubscribe to the channel.2026-04-18T10:42:54÷00:00 Good. Goodi2026-04-18T10:42:54+00:00 You want some?2026-04-18T10:43:40+00:00 Thanks for watching!2026-04-18T10:43:40+00:00 I'Il actually look back down.2026-04-18T10:44.25+00:00lust some Euro or aorchestrating now. Even thoug2026-04-18T10:44:25÷00:00 That's alli2026-04-18T10:44:47+00:00 Thank you.2026-04-18T10:47:22+00:00 Not a dog2026-04-18T10:47:22+00:00 More to go2026-04-18T10:47:52+00:00 Thank you.2026-04-18T10:47:52+00:00 So, this is our, this is the real,2026-04-18T10:48:22÷00:00 tvne ofl2026-04-18T10:48:22÷00:001ohone2026-04-18T10:52:21+00:00 Okay. Thanks for watchingdevicesystem AudioSystem Audiosystem AudiosoundcoreAeroclipsounacoreAeroClipounacotoAeroClipsoundcoreAeroClipsoundcoreAeroClinAeroCliosoundcoreAeroClipSvstem Audiolsystem AudiosoundcoreAeroClipsoundcoreAeroClinSystem Audiosystem AudioSystem AudioSvstem AudiolSvstem AudiolAeroClipsoundcoreAeroClipsoundcoreAoroClinsoundcoreAeroClipAerocllpsounacoreis inpur device speaker ld transcription engine Start timelFalseralseFalseTrueTrueTruelTruelTrueTrueTrueFalseFalseTrueTrueTrueFalseralseFalseFalselFalseTrueTrueTrueE TruelTrueWhisperlinvwhisperlinyWhisperlinyWhisperTinywhisperlinyWhisperlinyWhisperTinyWhisperTinyWhisperlinyWhisperTinyWhisperTinyWhisperTinyWhisperTinyWhisperTinyWhisperTinyWhisperTinyWhisperlinyWhisperTinyWhisoerTinyWhisnerTinvWhisperTinyWhisperTinyWhisperTinyWhisperTinyWhisnerTinvWhisoerTinyWhisperTinyendtimetext_length sync_id synced_at30.01630.01630.01626.0325625| 26.4375625 |1028.4794375 29.8631875 2824.5138125 24. .01622.0669375 24.1594[PHONE]6.8088125 29.8631[PHONE]625 8.786312513023.5856875 29.8631875 5018.1013125 |19.3163125 |1220.7844375 28.1756875 1520.3119375 27.6188125 2127.9394375 29.5931875 3012.7350625 18.6413125 7928.7325625 | 29.6269[PHONE]875 |1.833812525.5263125 26.1675625 1128.2600625 28800062522.3200625 23.7375625 1124.2775625 29. .1931875 25.9144375 27NULLNULUNULLINULLNULIINULLINULLNULLNULLINULLNULINULLINULLINULLNULLINULLINULLINULITNuL INULLNUTTTNULINULLNULLNULLNULLTNULLNULLNULLNULLNULTTNULLINULLNULLNULUNULLTNULLNULLNULLNULLNULITNULLNULTNULLINULLNULLNULL...
|
35
|
NULL
|
NULL
|
NULL
|
|
40
|
4
|
6
|
2026-05-06T17:31:01.602477+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778088661602_m2.jpg...
|
iTerm2
|
NULL
|
True
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
ActivityJiminny ... v• Drafts & sent8 Director ActivityJiminny ... v• Drafts & sent8 DirectoriesA External connections* Starredi& jiminny-x-integrati...platform-inner-team® Channels# ai-chapter# alerts# backend# bugs# confusion-clinic# curiosity_lab# engineering# general# jiminny-bg# platform-ticketsi product launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi...^ Direct messagesB Aneliya Angelova, ...Stovan Tanev €. Stefka Stoyanovaf. VesP. Galya DimitrovaAº. Aneliya AngelovaB. Vasil Vasilevdo James GrahamNikolav Ivanova Inkas Kovali•Annc@ Describe what you are looking forJira CloudHomeMessages 9+Status: In DeyNI Assignee: Nikolay IvanovT Priority: MCommentMore actions...Jira Cloua Arr 4:58 PM@Nikolay Ivanov transitioned a Story you are watching from Code RevJY-20/40 Kelease AJ Panorama reports to customersStatus: Keady for DeploymentTурe: StoryNI Assignee: Nikolay Ivanov* → CPull requests • screenpipe/screenpipe • GitHub# Hostinger login | Sign in to Hostinger accountLogin - Nginx Proxy Manager* Screenpipe - Archive* SQLite Web: archive.db©SQLite Web: db.sqlite@ screenpipe/ claude/skills at main • screenpipe/screenp- New TabJira Cloud APP 11:43 AM4 @Nikolay Ivanov transitioned a Story you are watching from Ready foJY-20740 Release AJ Panorama reports to customersCtatue. MonlovodNI Assignee: Nikolay Ivanov1 Priority: MelJira Cloud APP 5:52 PM@Nikolav Ivanov transitioned a Bug vou are watching from Tn Dev —JY-20699 Wrong formatting for summarv in the CRMStatus: Code Review• Type: BugNI Assienee: Nikolav Ivanov1 Prioritv: N@Nikolay Ivanov commented on a Bug you are watchingJY-20699 Wrong formatting for summary in the CRMBefore vs AfterJira Cloud APP 11:54 AM4 @Nikolay Ivanov transitioned a Bug you are watching from Code ReviJY-20699 Wrong formatting for summary in the CRM• Type: BugNI Assignee: Nikolay IvanovT Priority: MedlCommentMessage Jira Cloud+ AaNot Secure http://[IP_ADDRESS]:8768/audio_transcriptions_fts/sqlite-web 0.7.2db.sqlite audio_transcriptions_ftstable name..._sqlx_migrationsaudio_chunksaudio_tagsaudio_transcriptionsaudio transcriptions.fts (M)audio_tra audio. transcriptions.ftsaudio_transcriptions_.audio_transcriptions_.elementselements_fts (v)elements_fts_configelements_fts_dataelements_fts_idxframesframes_fts (v)frames_fts_configframes_fts_dataframes_fts_idxmeetingsmemoriesmemories_fts (v)memories_fts_configmemories_fts_datamemories_fts_idxocr_textpipe_executionspipe_scheduler_statesecretsspeaker_embeddingsspeakerssqlite_sequencesqlite_stat1sqlite_stat4tagsui_eventsui_events_fts (v)ui_events_fts_configstructureContentQueryExporiSQLCREATE VIRTUAL TABLE audio_transcriptions_fts USING fts5 (transcription,device,speaker1d,content='audio_transcriptions',content_rowid='id',, tokenize= unicode6'ColumnsColumnData typetranscriptiondevicespeaker_idIndexesNameColumnsSQLite database browser v0.7.2, powered by Flask and Peewee. © 2026 Charles LeiferAllow nullUniquePrimary keySOL95% C/2 & • Wed 6 May 20:31:02.Actionsread-onlyread-onlyread-onlvDrop?...
|
NULL
|
6617115144987980683
|
NULL
|
click
|
ocr
|
NULL
|
ActivityJiminny ... v• Drafts & sent8 Director ActivityJiminny ... v• Drafts & sent8 DirectoriesA External connections* Starredi& jiminny-x-integrati...platform-inner-team® Channels# ai-chapter# alerts# backend# bugs# confusion-clinic# curiosity_lab# engineering# general# jiminny-bg# platform-ticketsi product launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi...^ Direct messagesB Aneliya Angelova, ...Stovan Tanev €. Stefka Stoyanovaf. VesP. Galya DimitrovaAº. Aneliya AngelovaB. Vasil Vasilevdo James GrahamNikolav Ivanova Inkas Kovali•Annc@ Describe what you are looking forJira CloudHomeMessages 9+Status: In DeyNI Assignee: Nikolay IvanovT Priority: MCommentMore actions...Jira Cloua Arr 4:58 PM@Nikolay Ivanov transitioned a Story you are watching from Code RevJY-20/40 Kelease AJ Panorama reports to customersStatus: Keady for DeploymentTурe: StoryNI Assignee: Nikolay Ivanov* → CPull requests • screenpipe/screenpipe • GitHub# Hostinger login | Sign in to Hostinger accountLogin - Nginx Proxy Manager* Screenpipe - Archive* SQLite Web: archive.db©SQLite Web: db.sqlite@ screenpipe/ claude/skills at main • screenpipe/screenp- New TabJira Cloud APP 11:43 AM4 @Nikolay Ivanov transitioned a Story you are watching from Ready foJY-20740 Release AJ Panorama reports to customersCtatue. MonlovodNI Assignee: Nikolay Ivanov1 Priority: MelJira Cloud APP 5:52 PM@Nikolav Ivanov transitioned a Bug vou are watching from Tn Dev —JY-20699 Wrong formatting for summarv in the CRMStatus: Code Review• Type: BugNI Assienee: Nikolav Ivanov1 Prioritv: N@Nikolay Ivanov commented on a Bug you are watchingJY-20699 Wrong formatting for summary in the CRMBefore vs AfterJira Cloud APP 11:54 AM4 @Nikolay Ivanov transitioned a Bug you are watching from Code ReviJY-20699 Wrong formatting for summary in the CRM• Type: BugNI Assignee: Nikolay IvanovT Priority: MedlCommentMessage Jira Cloud+ AaNot Secure http://[IP_ADDRESS]:8768/audio_transcriptions_fts/sqlite-web 0.7.2db.sqlite audio_transcriptions_ftstable name..._sqlx_migrationsaudio_chunksaudio_tagsaudio_transcriptionsaudio transcriptions.fts (M)audio_tra audio. transcriptions.ftsaudio_transcriptions_.audio_transcriptions_.elementselements_fts (v)elements_fts_configelements_fts_dataelements_fts_idxframesframes_fts (v)frames_fts_configframes_fts_dataframes_fts_idxmeetingsmemoriesmemories_fts (v)memories_fts_configmemories_fts_datamemories_fts_idxocr_textpipe_executionspipe_scheduler_statesecretsspeaker_embeddingsspeakerssqlite_sequencesqlite_stat1sqlite_stat4tagsui_eventsui_events_fts (v)ui_events_fts_configstructureContentQueryExporiSQLCREATE VIRTUAL TABLE audio_transcriptions_fts USING fts5 (transcription,device,speaker1d,content='audio_transcriptions',content_rowid='id',, tokenize= unicode6'ColumnsColumnData typetranscriptiondevicespeaker_idIndexesNameColumnsSQLite database browser v0.7.2, powered by Flask and Peewee. © 2026 Charles LeiferAllow nullUniquePrimary keySOL95% C/2 & • Wed 6 May 20:31:02.Actionsread-onlyread-onlyread-onlvDrop?...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
42
|
4
|
7
|
2026-05-06T17:31:04.871533+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778088664871_m2.jpg...
|
iTerm2
|
NULL
|
True
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
ActivityJiminny ... v• Drafts & sent8 Director ActivityJiminny ... v• Drafts & sent8 DirectoriesA External connections* Starredi& jiminny-x-integrati...platform-inner-team® Channels# ai-chapter# alerts# backend# bugs# confusion-clinic# curiosity_lab# engineering# general# jiminny-bg# platform-ticketsi product launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi...^ Direct messagesB Aneliya Angelova, ...Stovan Tanev €. Stefka Stoyanovaf. VesP. Galya DimitrovaAº. Aneliya AngelovaB. Vasil Vasilevdo James GrahamNikolav Ivanova Inkas Kovali•Annc@ Describe what you are looking forJira CloudHomeMessages 9+Status: In DeyNI Assignee: Nikolay IvanovT Priority: MCommentMore actions...Jira Cloua Arr 4:58 PM@Nikolay Ivanov transitioned a Story you are watching from Code RevJY-20/40 Kelease AJ Panorama reports to customersStatus: Keady for Deployment• Type: StoryNI Assignee: Nikolay IvanovJira Cloud APP 11:43 AM4 @Nikolay Ivanov transitioned a Story you are watching from Ready foJY-20740 Release AJ Panorama reports to customersCtatue. MonlovodNI Assignee: Nikolay Ivanov1 Priority: MelJira Cloud APP 5:52 PM@Nikolav Ivanov transitioned a Bug vou are watching from Tn Dev —JY-20699 Wrong formatting for summarv in the CRMStatus: Code Review• Type: BugNI Assienee: Nikolav Ivanov1 Prioritv: N@Nikolay Ivanov commented on a Bug you are watchingJY-20699 Wrong formatting for summary in the CRMBefore vs After* → CPull requests • screenpipe/screenpipe • GitHub# Hostinger login | Sign in to Hostinger accountLogin - Nginx Proxy Manager* Screenpipe - Archive* SQLite Web: archive.db©SQLite Web: db.sqlite@ screenpipe/ claude/skills at main • screenpipe/screenp- New TabJira Cloud APP 11:54 AM4 @Nikolay Ivanov transitioned a Bug you are watching from Code ReviJY-20699 Wrong formatting for summary in the CRM• Type: BugNI Assignee: Nikolay IvanovT Priority: MedlCommentMessage Jira Cloud+ AaNot Secure http://[IP_ADDRESS]:8768/audio_transcriptions_fts_idx/sqlite-web 0.7.2db.sqlite audio_transcriptions_fts_idxtable name..._sqlx_migrationsaudio chunksaudio_tagsaudio_transcriptionsaudio_transcriptions_fts (v)audio_transcriptions_.audio_transcriptions_...audio-transcriptions...elementselements_fts (v)elements_fts_onfigelements_fts_dataelements_fts_idxframesframes_fts (v)frames_fts_configframes_fts_dataframes_fts_idxmeetingsmemoriesmemories_fts (v)memories_fts_configmemories_fts_datamemories_fts_idxocr_textpipe_executionspipe_scheduler_statesecretsspeaker_embeddingsspeakerssqlite_sequencesqlite_stat1sqlite_stat4tagsui_eventsui_events_fts (v)ui_events_fts_configui_events_fts_datastructureContentQueryExporiSQLCREATE TABLE 'audio_transcriptions_fts_idx'(sopta,, Barin ertsegid, erem)ColumnsColumnData typesegidtermpgnoIndexesColumnsSQLite database browser v0.7.2, powered by Flask and Peewee. © 2026 Charles LeiferAllow nullUniquePrimary keySQL• 95% C2 8• Wed 6 May 20:31:05Actionsread-onlyread-onlyread-onlyDrop?...
|
NULL
|
1143259276590902786
|
NULL
|
visual_change
|
ocr
|
NULL
|
ActivityJiminny ... v• Drafts & sent8 Director ActivityJiminny ... v• Drafts & sent8 DirectoriesA External connections* Starredi& jiminny-x-integrati...platform-inner-team® Channels# ai-chapter# alerts# backend# bugs# confusion-clinic# curiosity_lab# engineering# general# jiminny-bg# platform-ticketsi product launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi...^ Direct messagesB Aneliya Angelova, ...Stovan Tanev €. Stefka Stoyanovaf. VesP. Galya DimitrovaAº. Aneliya AngelovaB. Vasil Vasilevdo James GrahamNikolav Ivanova Inkas Kovali•Annc@ Describe what you are looking forJira CloudHomeMessages 9+Status: In DeyNI Assignee: Nikolay IvanovT Priority: MCommentMore actions...Jira Cloua Arr 4:58 PM@Nikolay Ivanov transitioned a Story you are watching from Code RevJY-20/40 Kelease AJ Panorama reports to customersStatus: Keady for Deployment• Type: StoryNI Assignee: Nikolay IvanovJira Cloud APP 11:43 AM4 @Nikolay Ivanov transitioned a Story you are watching from Ready foJY-20740 Release AJ Panorama reports to customersCtatue. MonlovodNI Assignee: Nikolay Ivanov1 Priority: MelJira Cloud APP 5:52 PM@Nikolav Ivanov transitioned a Bug vou are watching from Tn Dev —JY-20699 Wrong formatting for summarv in the CRMStatus: Code Review• Type: BugNI Assienee: Nikolav Ivanov1 Prioritv: N@Nikolay Ivanov commented on a Bug you are watchingJY-20699 Wrong formatting for summary in the CRMBefore vs After* → CPull requests • screenpipe/screenpipe • GitHub# Hostinger login | Sign in to Hostinger accountLogin - Nginx Proxy Manager* Screenpipe - Archive* SQLite Web: archive.db©SQLite Web: db.sqlite@ screenpipe/ claude/skills at main • screenpipe/screenp- New TabJira Cloud APP 11:54 AM4 @Nikolay Ivanov transitioned a Bug you are watching from Code ReviJY-20699 Wrong formatting for summary in the CRM• Type: BugNI Assignee: Nikolay IvanovT Priority: MedlCommentMessage Jira Cloud+ AaNot Secure http://[IP_ADDRESS]:8768/audio_transcriptions_fts_idx/sqlite-web 0.7.2db.sqlite audio_transcriptions_fts_idxtable name..._sqlx_migrationsaudio chunksaudio_tagsaudio_transcriptionsaudio_transcriptions_fts (v)audio_transcriptions_.audio_transcriptions_...audio-transcriptions...elementselements_fts (v)elements_fts_onfigelements_fts_dataelements_fts_idxframesframes_fts (v)frames_fts_configframes_fts_dataframes_fts_idxmeetingsmemoriesmemories_fts (v)memories_fts_configmemories_fts_datamemories_fts_idxocr_textpipe_executionspipe_scheduler_statesecretsspeaker_embeddingsspeakerssqlite_sequencesqlite_stat1sqlite_stat4tagsui_eventsui_events_fts (v)ui_events_fts_configui_events_fts_datastructureContentQueryExporiSQLCREATE TABLE 'audio_transcriptions_fts_idx'(sopta,, Barin ertsegid, erem)ColumnsColumnData typesegidtermpgnoIndexesColumnsSQLite database browser v0.7.2, powered by Flask and Peewee. © 2026 Charles LeiferAllow nullUniquePrimary keySQL• 95% C2 8• Wed 6 May 20:31:05Actionsread-onlyread-onlyread-onlyDrop?...
|
40
|
NULL
|
NULL
|
NULL
|
|
43
|
4
|
8
|
2026-05-06T17:31:08.555399+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778088668555_m2.jpg...
|
iTerm2
|
NULL
|
True
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
ActivityJiminny ... v• Drafts & sent8 Director ActivityJiminny ... v• Drafts & sent8 DirectoriesA External connections* Starredi& jiminny-x-integrati...platform-inner-team® Channels# ai-chapter# alerts# backend# bugs# confusion-clinic# curiosity_lab# engineering# general# jiminny-bg# platform-ticketsi product launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi...^ Direct messagesB Aneliya Angelova, ...5 Stovan Tanev €. Stefka Stoyanovaf. VesP. Galya DimitrovaAº. Aneliya AngelovaB. Vasil Vasilevdo James GrahamNikolav IvanovInkas Kovali•Annc@ Describe what you are looking forJira CloudHomeMessages 9+Status: In DeyNI Assignee: Nikolay IvanovT Priority: MCommentMore actions...Jira Cloua Arr 4:58 PM@Nikolay Ivanov transitioned a Story you are watching from Code RevJY-20/40 Kelease AJ Panorama reports to customersStatus: Keady for Deployment• Type: StoryNI Assignee: Nikolay Ivanov* → CPull requests • screenpipe/screenpipe • GitHub# Hostinger login | Sign in to Hostinger accountLogin - Nginx Proxy Manager* Screenpipe - Archive* SQLite Web: archive.db©SQLite Web: db.sqlite@ screenpipe/ claude/skills at main • screenpipe/screenp- New TabJira Cloud APP 11:43 AM4 @Nikolay Ivanov transitioned a Story you are watching from Ready foJY-20740 Release AJ Panorama reports to customersCtatue. MonlovodNI Assignee: Nikolay Ivanov1 Priority: MelJira Cloud APP 5:52 PM@Nikolav Ivanov transitioned a Bug vou are watching from Tn Dev —JY-20699 Wrong formatting for summarv in the CRMStatus: Code Review• Type: BugNI Assienee: Nikolay Ivanov1 Prioritv: N@Nikolay Ivanov commented on a Bug you are watchingJY-20699 Wrong formatting for summary in the CRMBefore vs AfterJira Cloud APP 11:54 AM4 @Nikolay Ivanov transitioned a Bug you are watching from Code ReviJY-20699 Wrong formatting for summary in the CRM• Type: BugNI Assignee: Nikolay IvanovT Priority: MedlCommentMessage Jira Cloud+ AaNot Secure http://[IP_ADDRESS]:8768/audio_transcriptions_fts_idx/CREATE TABLE 'audio_transcriptions_fts_idx'(audio_transcriptionssegid,audio_transcriptions_fts (v)term,pgno,audio_transcriptions_.PRIMARY KEY(segid, term)audio transcriotionsaudio_transcriptions_...Columnselementselements_fts (v)ColumnData typeelements_fts_configsegidelements_fts_dataelements_fts_idxtermframesframes_fts (")frames_fts_configframes_fts_dataIndexesframes_fts_idxmeetingsColumnsmemoriesmemories_fts (v)SOLite database browser v0.7.2. powered by Flask and Peewee. © 2026 Charles Leifermemories_fts_configmemories_fts_data dmemories_fts_idxocr_textpipe_executionspipe_scheduler_statesecretsspeaker_embeddingsspeakerssqlite_sequencesqlite_stat1sqlite_stat4tagsui_eventsui_events_fts (v)ui_events_fts_configui_events_fts_dataui_events_fts_idxvideo_chunksvision_tagsToggle helper tablesAllow nullUniqueries fts datalPrimary keySQLS• Wd6May 20:31:09Actionsread-onlyread-onlyread-onlyDrop?...
|
NULL
|
-1850853932199179698
|
NULL
|
visual_change
|
ocr
|
NULL
|
ActivityJiminny ... v• Drafts & sent8 Director ActivityJiminny ... v• Drafts & sent8 DirectoriesA External connections* Starredi& jiminny-x-integrati...platform-inner-team® Channels# ai-chapter# alerts# backend# bugs# confusion-clinic# curiosity_lab# engineering# general# jiminny-bg# platform-ticketsi product launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi...^ Direct messagesB Aneliya Angelova, ...5 Stovan Tanev €. Stefka Stoyanovaf. VesP. Galya DimitrovaAº. Aneliya AngelovaB. Vasil Vasilevdo James GrahamNikolav IvanovInkas Kovali•Annc@ Describe what you are looking forJira CloudHomeMessages 9+Status: In DeyNI Assignee: Nikolay IvanovT Priority: MCommentMore actions...Jira Cloua Arr 4:58 PM@Nikolay Ivanov transitioned a Story you are watching from Code RevJY-20/40 Kelease AJ Panorama reports to customersStatus: Keady for Deployment• Type: StoryNI Assignee: Nikolay Ivanov* → CPull requests • screenpipe/screenpipe • GitHub# Hostinger login | Sign in to Hostinger accountLogin - Nginx Proxy Manager* Screenpipe - Archive* SQLite Web: archive.db©SQLite Web: db.sqlite@ screenpipe/ claude/skills at main • screenpipe/screenp- New TabJira Cloud APP 11:43 AM4 @Nikolay Ivanov transitioned a Story you are watching from Ready foJY-20740 Release AJ Panorama reports to customersCtatue. MonlovodNI Assignee: Nikolay Ivanov1 Priority: MelJira Cloud APP 5:52 PM@Nikolav Ivanov transitioned a Bug vou are watching from Tn Dev —JY-20699 Wrong formatting for summarv in the CRMStatus: Code Review• Type: BugNI Assienee: Nikolay Ivanov1 Prioritv: N@Nikolay Ivanov commented on a Bug you are watchingJY-20699 Wrong formatting for summary in the CRMBefore vs AfterJira Cloud APP 11:54 AM4 @Nikolay Ivanov transitioned a Bug you are watching from Code ReviJY-20699 Wrong formatting for summary in the CRM• Type: BugNI Assignee: Nikolay IvanovT Priority: MedlCommentMessage Jira Cloud+ AaNot Secure http://[IP_ADDRESS]:8768/audio_transcriptions_fts_idx/CREATE TABLE 'audio_transcriptions_fts_idx'(audio_transcriptionssegid,audio_transcriptions_fts (v)term,pgno,audio_transcriptions_.PRIMARY KEY(segid, term)audio transcriotionsaudio_transcriptions_...Columnselementselements_fts (v)ColumnData typeelements_fts_configsegidelements_fts_dataelements_fts_idxtermframesframes_fts (")frames_fts_configframes_fts_dataIndexesframes_fts_idxmeetingsColumnsmemoriesmemories_fts (v)SOLite database browser v0.7.2. powered by Flask and Peewee. © 2026 Charles Leifermemories_fts_configmemories_fts_data dmemories_fts_idxocr_textpipe_executionspipe_scheduler_statesecretsspeaker_embeddingsspeakerssqlite_sequencesqlite_stat1sqlite_stat4tagsui_eventsui_events_fts (v)ui_events_fts_configui_events_fts_dataui_events_fts_idxvideo_chunksvision_tagsToggle helper tablesAllow nullUniqueries fts datalPrimary keySQLS• Wd6May 20:31:09Actionsread-onlyread-onlyread-onlyDrop?...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
44
|
4
|
9
|
2026-05-06T17:31:11.392105+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778088671392_m2.jpg...
|
iTerm2
|
NULL
|
True
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
ActivityJiminny ... v• Drafts & sent8 Director ActivityJiminny ... v• Drafts & sent8 DirectoriesA External connections* Starredi& jiminny-x-integrati...platform-inner-team® Channels# ai-chapter# alerts# backend# bugs# confusion-clinic# curiosity_lab# engineering# general# jiminny-bg# platform-ticketsi product launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi...^ Direct messagesB Aneliya Angelova, ...Stovan Tanev €. Stefka Stoyanovaf. VesP. Galya DimitrovaAº. Aneliya AngelovaB. Vasil Vasilevdo James GrahamNikolav IvanovInkas Kovali•Annc@ Describe what you are looking forJira CloudHomeMessages 9+Status: In DeyNI Assignee: Nikolay IvanovT Priority: MCommentMore actions...Jira Cloua Arr 4:58 PM@Nikolay Ivanov transitioned a Story you are watching from Code RevJY-20/40 Kelease AJ Panorama reports to customersStatus: Keady for DeploymentTурe: StoryNI Assignee: Nikolay Ivanov* → CPull requests • screenpipe/screenpipe • GitHub# Hostinger login | Sign in to Hostinger account© Login - Nginx Proxy Manager* Screenpipe - Archive* SQLite Web: archive.db©SQLite Web: db.sqlite@ screenpipe/ claude/skills at main • screenpipe/screenp- New TabJira Cloud APP 11:43 AM4 @Nikolay Ivanov transitioned a Story you are watching from Ready foJY-20740 Release AJ Panorama reports to customersCtatue. MonlovodNI Assignee: Nikolay Ivanov1 Priority: MelJira Cloud APP 5:52 PM@Nikolav Ivanov transitioned a Bug vou are watching from Tn Dev —JY-20699 Wrong formatting for summarv in the CRMStatus: Code Review• Type: BugNI Assienee: Nikolay Ivanov1 Prioritv: N@Nikolay Ivanov commented on a Bug you are watchingJY-20699 Wrong formatting for summary in the CRMBefore vs AfterJira Cloud APP 11:54 AM4 @Nikolay Ivanov transitioned a Bug you are watching from Code ReviJY-20699 Wrong formatting for summary in the CRM• Type: BugNI Assignee: Nikolay IvanovT Priority: MedlCommentMessage Jira Cloud+ AaO 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_stat1sqlite_stat4tagsui_events &ui_events_fts (v)ui_events_fts_configui_events_fts_dataui_events_fts_idxvideo_chunksvision_tagsCREATE TABLE 'audio_transcriptions_fts_idx' (segid,term,pgno,PRIMARY KEY(segid, term)ColumnsColumnData typesegidpgnoIndexesNameColumnsSQLite database browser v0.7.2, powered by Flask and Peewee. © 2026 Charles LeiferToggle helper tableshttp://192.1680.242:8768/ui eventsAllow nullUniquePrimary keySOLX 95% C/2 8• Wed 6 May 20:31:12.Actionsread-onlyread-onlyread-onlyDrop?...
|
NULL
|
-8517015082153896664
|
NULL
|
visual_change
|
ocr
|
NULL
|
ActivityJiminny ... v• Drafts & sent8 Director ActivityJiminny ... v• Drafts & sent8 DirectoriesA External connections* Starredi& jiminny-x-integrati...platform-inner-team® Channels# ai-chapter# alerts# backend# bugs# confusion-clinic# curiosity_lab# engineering# general# jiminny-bg# platform-ticketsi product launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi...^ Direct messagesB Aneliya Angelova, ...Stovan Tanev €. Stefka Stoyanovaf. VesP. Galya DimitrovaAº. Aneliya AngelovaB. Vasil Vasilevdo James GrahamNikolav IvanovInkas Kovali•Annc@ Describe what you are looking forJira CloudHomeMessages 9+Status: In DeyNI Assignee: Nikolay IvanovT Priority: MCommentMore actions...Jira Cloua Arr 4:58 PM@Nikolay Ivanov transitioned a Story you are watching from Code RevJY-20/40 Kelease AJ Panorama reports to customersStatus: Keady for DeploymentTурe: StoryNI Assignee: Nikolay Ivanov* → CPull requests • screenpipe/screenpipe • GitHub# Hostinger login | Sign in to Hostinger account© Login - Nginx Proxy Manager* Screenpipe - Archive* SQLite Web: archive.db©SQLite Web: db.sqlite@ screenpipe/ claude/skills at main • screenpipe/screenp- New TabJira Cloud APP 11:43 AM4 @Nikolay Ivanov transitioned a Story you are watching from Ready foJY-20740 Release AJ Panorama reports to customersCtatue. MonlovodNI Assignee: Nikolay Ivanov1 Priority: MelJira Cloud APP 5:52 PM@Nikolav Ivanov transitioned a Bug vou are watching from Tn Dev —JY-20699 Wrong formatting for summarv in the CRMStatus: Code Review• Type: BugNI Assienee: Nikolay Ivanov1 Prioritv: N@Nikolay Ivanov commented on a Bug you are watchingJY-20699 Wrong formatting for summary in the CRMBefore vs AfterJira Cloud APP 11:54 AM4 @Nikolay Ivanov transitioned a Bug you are watching from Code ReviJY-20699 Wrong formatting for summary in the CRM• Type: BugNI Assignee: Nikolay IvanovT Priority: MedlCommentMessage Jira Cloud+ AaO 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_stat1sqlite_stat4tagsui_events &ui_events_fts (v)ui_events_fts_configui_events_fts_dataui_events_fts_idxvideo_chunksvision_tagsCREATE TABLE 'audio_transcriptions_fts_idx' (segid,term,pgno,PRIMARY KEY(segid, term)ColumnsColumnData typesegidpgnoIndexesNameColumnsSQLite database browser v0.7.2, powered by Flask and Peewee. © 2026 Charles LeiferToggle helper tableshttp://192.1680.242:8768/ui eventsAllow nullUniquePrimary keySOLX 95% C/2 8• Wed 6 May 20:31:12.Actionsread-onlyread-onlyread-onlyDrop?...
|
43
|
NULL
|
NULL
|
NULL
|
|
46
|
4
|
10
|
2026-05-06T17:31:25.154539+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778088685154_m2.jpg...
|
iTerm2
|
NULL
|
True
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
ActivityFllesLaterMoreslackHistoryWindowHelpVIewJi ActivityFllesLaterMoreslackHistoryWindowHelpVIewJiminny...yDratts & sent.8 DirectoriesA External connections** Starredi8 jiminny-x-integrati...platform-inner-team® Channels#al-chapter# alerts# backend# bugs# confusion-clinic# curiosity_lab# engineering# general# jiminny-bg# platform-ticketsi product aunches# random# releases# sofia-office# sugnortithank-vous# the_people_of jimi...• Direct messagesB Aneliya Angelova, ...2. Stoyan Tanev •. Stefka Stoyanovaf. VesP. Galya DimitrovaAº. Aneliya AngelovaehVasil Vasileydo James GrahamNikolav Ivanov8 Inkas Kovali•AnncQ Describe what you are looking for# support8360Messagese Files• Bookmarks* PinsStatus. backiogType: Bug+ Al SummariseAssignee. UnassignedT Priority: MMonday. April 27thvSync threadAdded by lira cloudTuesday. April 28thvKara Jones 5:01 PMwas added to #support by Greg.Wednesday. April 29thvLauren Hudson 12:58 PMHi team, I'm trying to set up auto detect for Les Mills, but when I add a new playbook (because they want it applied across all teams), it's pulling in a load of activity typesthat I am not able to delete. Any ideas please?Screenchot 2026.04.29 at 10 54 42 nng -(Q 1 reply 7 days agoLauren Hudson 6:17 PMHello, request from Norstella to update their Jiminny to match this shared spreadsheet. Is somebody from the support team able to help please?Numhers DocumentCommorcial Poctor. 2024|Cammorcial Pactor) min…*F/A 3 replies Last reply 1 day agoToday• NewLauren Hudson 6:03 PMHello, can somebody loop me into the conversation around Dingus & Zazzy (Enoch's) request for us to provide transcripts / video for them ahead of them leaving? Thankg 3 replies Last reply today at 8:17 PMMessage #support+ Aao_transcriptions_fts_idx/CREATE TABLE 'audio_transcriptions_fts_idx' (segid,term,vgno,PRIMARY KEY(segid, term)ColumnsColumnsegidtermpgnoIndexesNameData typeColumnsSQLite database browser v0.7.2, powered by Flask and Peewee. © 2026 Charles LeiferAllow nullUniqueOOOAT 948 WedGMay 20:31:26Primary keySOLActionsread-onlyread-onlyread-onlyDrop?...
|
NULL
|
-9006001265253355058
|
NULL
|
visual_change
|
ocr
|
NULL
|
ActivityFllesLaterMoreslackHistoryWindowHelpVIewJi ActivityFllesLaterMoreslackHistoryWindowHelpVIewJiminny...yDratts & sent.8 DirectoriesA External connections** Starredi8 jiminny-x-integrati...platform-inner-team® Channels#al-chapter# alerts# backend# bugs# confusion-clinic# curiosity_lab# engineering# general# jiminny-bg# platform-ticketsi product aunches# random# releases# sofia-office# sugnortithank-vous# the_people_of jimi...• Direct messagesB Aneliya Angelova, ...2. Stoyan Tanev •. Stefka Stoyanovaf. VesP. Galya DimitrovaAº. Aneliya AngelovaehVasil Vasileydo James GrahamNikolav Ivanov8 Inkas Kovali•AnncQ Describe what you are looking for# support8360Messagese Files• Bookmarks* PinsStatus. backiogType: Bug+ Al SummariseAssignee. UnassignedT Priority: MMonday. April 27thvSync threadAdded by lira cloudTuesday. April 28thvKara Jones 5:01 PMwas added to #support by Greg.Wednesday. April 29thvLauren Hudson 12:58 PMHi team, I'm trying to set up auto detect for Les Mills, but when I add a new playbook (because they want it applied across all teams), it's pulling in a load of activity typesthat I am not able to delete. Any ideas please?Screenchot 2026.04.29 at 10 54 42 nng -(Q 1 reply 7 days agoLauren Hudson 6:17 PMHello, request from Norstella to update their Jiminny to match this shared spreadsheet. Is somebody from the support team able to help please?Numhers DocumentCommorcial Poctor. 2024|Cammorcial Pactor) min…*F/A 3 replies Last reply 1 day agoToday• NewLauren Hudson 6:03 PMHello, can somebody loop me into the conversation around Dingus & Zazzy (Enoch's) request for us to provide transcripts / video for them ahead of them leaving? Thankg 3 replies Last reply today at 8:17 PMMessage #support+ Aao_transcriptions_fts_idx/CREATE TABLE 'audio_transcriptions_fts_idx' (segid,term,vgno,PRIMARY KEY(segid, term)ColumnsColumnsegidtermpgnoIndexesNameData typeColumnsSQLite database browser v0.7.2, powered by Flask and Peewee. © 2026 Charles LeiferAllow nullUniqueOOOAT 948 WedGMay 20:31:26Primary keySOLActionsread-onlyread-onlyread-onlyDrop?...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
47
|
4
|
11
|
2026-05-06T17:31:35.364869+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778088695364_m2.jpg...
|
iTerm2
|
NULL
|
True
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
slackVIewHistoryWindowHelpAC.MILVHomeActivitsMoreA slackVIewHistoryWindowHelpAC.MILVHomeActivitsMoreAll 4DMsloastApp[no preview availablel11 | 10:00 AMIMonday. May 4thJira Cloud@Nikolay Ivanov transitioned aBug you are watching from Code...Wednesday, April 29thAneliva AngelovaWednesdayStoyan Tanev6 DMWednesdavнаша стоананTuesday. April 28th1 Stefka StoyanovaApr 28thтия тикети е добре да влезнат вдругия спринт ли? сложете някакви...Fe Thread in DM: искаж да т..Apr 28thсмони ro p Circle Cll eny нa нopuaтокон който си наппарилStefka Stoyano… Replied Apr 28thAOMIприятна отпуска ®Stetka Stovanova and …... Aor 28thlQ Describe what you are looking forN& Adelina Petrova "MessagesLo Add canvasUr Filesне, само стр се тракватThursday, April 23rdLukas Kovalik IN 1:15 PMAdelina Petrova "T 1:42 PMpagesLukas Kovalik "T 1:43 PMAdelina Petrova 5:06 PMда не ои проолема да е заради това кю: QUEUE,DELAYABLELukas Kovalik * 5:06 PMза това искам да дооавя логовеAdelina Petrova 5:07 PMVAVDA MO CTAUO SUA CA MAVUOLI?има ли риск за нещоLukas Kovalik " 5:08 PMвсишност нама опашка тукаAdelina Petrova " 5:12 PM• сега, няма ли ла сложи евента в това кюю и ла чака изпьлнение?Lukas Kovalik #* 5:21 PMла, ше оставя detault изпь лнениеLukas Kovalik 1K 5-26 PMпо поинцип го направих като nudge-created че те не са обвръзани с накакво конкретно achvity•и глелам че и този event няма никойAdelina Petrova" 5:33PMспорел мен пробвай без това кюLukas Kovalik * 5:33 PMhttps://run.userpilot.io/events/tracked_event/10run.userpilot.ioUserpilotUserpilot helps product teams deliver personalized in-app experiences to increasegrowth metrics at every stage of the user lournev.не е това обаче, гледам че всички си минават през сьщия флов и тези със activityAdelina Petrova * 5:40 PMами эко можеш сложи тогава лог да го видимAdelina Petrova has paused their notificationsMessage Adelina Petrova " VacationingAao_transcriptions_fts_idx/CREATE TABLE 'audio_transcriptions_fts_idx'(segid,term,vgno,PRIMARY KEY(segid, term)ColumnsColumnsegidtermpgnoIndexesNameData typeColumnsSQLite database browser v0.7.2, powered by Flask and Peewee. © 2026 Charles LeiferAllow nullUniqueOOOAX 48 WedGMay 20:31:36Primary keySOLActionsread-onlyread-onlyread-onlyDrop?...
|
NULL
|
-8841640919470731655
|
NULL
|
click
|
ocr
|
NULL
|
slackVIewHistoryWindowHelpAC.MILVHomeActivitsMoreA slackVIewHistoryWindowHelpAC.MILVHomeActivitsMoreAll 4DMsloastApp[no preview availablel11 | 10:00 AMIMonday. May 4thJira Cloud@Nikolay Ivanov transitioned aBug you are watching from Code...Wednesday, April 29thAneliva AngelovaWednesdayStoyan Tanev6 DMWednesdavнаша стоананTuesday. April 28th1 Stefka StoyanovaApr 28thтия тикети е добре да влезнат вдругия спринт ли? сложете някакви...Fe Thread in DM: искаж да т..Apr 28thсмони ro p Circle Cll eny нa нopuaтокон който си наппарилStefka Stoyano… Replied Apr 28thAOMIприятна отпуска ®Stetka Stovanova and …... Aor 28thlQ Describe what you are looking forN& Adelina Petrova "MessagesLo Add canvasUr Filesне, само стр се тракватThursday, April 23rdLukas Kovalik IN 1:15 PMAdelina Petrova "T 1:42 PMpagesLukas Kovalik "T 1:43 PMAdelina Petrova 5:06 PMда не ои проолема да е заради това кю: QUEUE,DELAYABLELukas Kovalik * 5:06 PMза това искам да дооавя логовеAdelina Petrova 5:07 PMVAVDA MO CTAUO SUA CA MAVUOLI?има ли риск за нещоLukas Kovalik " 5:08 PMвсишност нама опашка тукаAdelina Petrova " 5:12 PM• сега, няма ли ла сложи евента в това кюю и ла чака изпьлнение?Lukas Kovalik #* 5:21 PMла, ше оставя detault изпь лнениеLukas Kovalik 1K 5-26 PMпо поинцип го направих като nudge-created че те не са обвръзани с накакво конкретно achvity•и глелам че и този event няма никойAdelina Petrova" 5:33PMспорел мен пробвай без това кюLukas Kovalik * 5:33 PMhttps://run.userpilot.io/events/tracked_event/10run.userpilot.ioUserpilotUserpilot helps product teams deliver personalized in-app experiences to increasegrowth metrics at every stage of the user lournev.не е това обаче, гледам че всички си минават през сьщия флов и тези със activityAdelina Petrova * 5:40 PMами эко можеш сложи тогава лог да го видимAdelina Petrova has paused their notificationsMessage Adelina Petrova " VacationingAao_transcriptions_fts_idx/CREATE TABLE 'audio_transcriptions_fts_idx'(segid,term,vgno,PRIMARY KEY(segid, term)ColumnsColumnsegidtermpgnoIndexesNameData typeColumnsSQLite database browser v0.7.2, powered by Flask and Peewee. © 2026 Charles LeiferAllow nullUniqueOOOAX 48 WedGMay 20:31:36Primary keySOLActionsread-onlyread-onlyread-onlyDrop?...
|
46
|
NULL
|
NULL
|
NULL
|
|
49
|
4
|
12
|
2026-05-06T17:31:39.449364+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778088699449_m2.jpg...
|
iTerm2
|
NULL
|
True
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
DMSrireroxcalVIewHistorybookmarksProtllesHelpAC.MI DMSrireroxcalVIewHistorybookmarksProtllesHelpAC.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приятна отпуска ®Stetka Stovanova and …... Aor 28thlWindow* → CN& 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,DELAYALukas Kovalik * 5:06 PMscreenpipe/,claude/skills at main • screenpipe/screenpI Now Tabза това искам да дооавя логове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 че те не са оl•и глелам че и този 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 " VacationingAaONot 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,pgno,PRIMARY KEY(segid, term)ColumnsColumnData typesegidpgnoIndexesNameColumnsSQLite database browser v0.7.2, powered by Flask and Peewee. © 2026 Charles LeiferToggle helper tablesAllow nullUniqueOOOAA 94 . Wed6May 20:31:40Primary keySOLActionsread-onlyread-onlyread-onlyDrop?...
|
NULL
|
5055753413428530684
|
NULL
|
click
|
ocr
|
NULL
|
DMSrireroxcalVIewHistorybookmarksProtllesHelpAC.MI DMSrireroxcalVIewHistorybookmarksProtllesHelpAC.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приятна отпуска ®Stetka Stovanova and …... Aor 28thlWindow* → CN& 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,DELAYALukas Kovalik * 5:06 PMscreenpipe/,claude/skills at main • screenpipe/screenpI Now Tabза това искам да дооавя логове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 че те не са оl•и глелам че и този 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 " VacationingAaONot 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,pgno,PRIMARY KEY(segid, term)ColumnsColumnData typesegidpgnoIndexesNameColumnsSQLite database browser v0.7.2, powered by Flask and Peewee. © 2026 Charles LeiferToggle helper tablesAllow nullUniqueOOOAA 94 . Wed6May 20:31:40Primary keySOLActionsread-onlyread-onlyread-onlyDrop?...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
102
|
7
|
11
|
2026-05-06T17:43:40.387088+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778089420387_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:34
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:34","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"}]...
|
-5614177441283598860
|
7091811296981293686
|
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:34
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-zshX3-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)lukasstaff20842417Apr 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:}Luka»00:33X4screenpipe*X597% <4Wed 6 May 20:43:40TX1-zshX602:10...
|
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
|
|
103
|
7
|
12
|
2026-05-06T17:43:43.706137+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778089423706_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:24
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:24","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"}]...
|
9083833690402723101
|
7064790798728698486
|
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:24
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:24-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:431X1-zshX6X5Qu you‹ › x»02:10...
|
102
|
/Users/lukas/.screenpipe/data/data/2026-05-06/comp /Users/lukas/.screenpipe/data/data/2026-05-06/compact_monitor_1_1778089220643.mp4...
|
NULL
|
NULL
|
|
106
|
7
|
13
|
2026-05-06T17:43:47.043743+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-06/1778 /Users/lukas/.screenpipe/data/data/2026-05-06/1778089427043_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
01:39
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":"01:39","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"}]...
|
-8650028831773185902
|
7091812362133183222
|
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
01:39
toggle elapsed time, timecode and framecount
02:10
toggle duration and remaining time
document actions
compact_monitor_1_1778089220643.mp4
QuickTime PlayerFileEditViewWindowHelpcompact_monitor_1_1778089220643.mp4 v-zshX3-zsh-rw-DEV (docker)-rw--rw-I-rw-i-rw-!-rW-I-rw-!-rw-I-rw--rw--rW-I-rw-!-rw-1DOCKER"SNAS_DATA/STARGET_DATE/"2»>"SLOG_FILE"RSYNC_DUR=SCC S(date +%s) - RSYNC_START ))COPIED_FILES=S(Ls "SNAS_DATA/STARGET_DATE* | wc -1 l tr -d * *)SRC_FILES-S(ls "SDATA_SRC" | wc -1 l tr -d * ')COPIED_SIZE-S(du -sh "SNAS_DATA/STARGET_DATE" | cut -f1)if [ "SCOPIED_FILES" -eq"SSRC_FILES" ]; thenprintf "\r%-36s / %dm%02ds(%s files, %s)\n* \*rsync STARGET_DATE/ + NAS" \"S(( RSYNC_DUR / 60 ))" "S(( RSYNC_DUR % 60 ))"\"SCOPIED_FILES" "SCOPIED_SIZE" | tee -a "SLOG_FILE"printf "\rAPP (-zsh)else-rw-i-rw-ifi%-365 x %s /%s files\n""rsync STARGET_DATE/ → NAS" "SCOPIED_FILES" "SSRC_FILES" I tee -a "SLOG_FILE"-rw-else-rw-iprintf "%-36s %s\n" "rsync STARGET_DATE/ → NAS" "skipped (no source dir)"-rw-1fi-rw--rw-lSUMMARY-rW-TOTAL_ELAPSED=S(C S(date +%s) - SCRIPT_START ))-rw-DB_SIZE=S(du -sh "SNAS_DB" | cut -f1)-rw-Iecho-rw-i-rw-!109"Archive DB size:SDB_SIZE"10g"Total time:S(( TOTAL_ELAPSED / 60 ))MS(( TOTAL_ELAPSED % 60 ))s*-rw-i1og"Sync complete for STARGET_DATE"-rw-i109".ukas@Lukas-Kovaliks-MacBook-Pro-Jiminny~/.screenpipe $ 11-rw--rw-ltotaldrwxr-xr-x2 lukasstaff646 May20:22-rW-drwx94 lukas-rw-istaff30086 May20:27-rw-1lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny~/.screenpipe $ cd ..lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $cd ~/.screenpipe-rw-ilukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ l1-rw-ltotal-rw-i9424drwxr-xr-x8 lukasstaff256-rw-i6 May20:2701:39drwx---~--+94lukasstaff30086 May20:27-rw-| drwxr-xr-x5lukasstaff1606 Маy20:28data-rw-il-rw-r--r--lukasstaff5816326 May20:27-rw-l-rw-r--r--lukasstaff327686 May20:27db.sqlitelukasstaff331251220:28db.sqlite-shm-rW--rw-r--r--16 May-rw-idrwxr-xr-x825620:27db.sqlite-wallukasstaff6 Maypipesluka:-rw-r--r--1lukasstaff95666 Мay20:28screenpipe.2026-05-06.0.10gLukakas@Lukas-Kovaliks-MacBook-Pro-Jiminny~/.screenpipeX4screenpipeA97% <4Wed 6 May 20:43:48X5-zshX6»02:10...
|
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
|