|
-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...
|
iTerm2
|
screenpipe"
|
NULL
|
|
-rw-r--r-- 1 lukas staff 3298542 28 Apr 18:07 -rw-r--r-- 1 lukas staff 3298542 28 Apr 18:07 compact_monitor_2_1777388874095.mp4
-rw-r--r-- 1 lukas staff 2143027 28 Apr 18:13 compact_monitor_2_1777389196097.mp4
-rw-r--r-- 1 lukas staff 2448311 28 Apr 18:18 compact_monitor_2_1777389532297.mp4
-rw-r--r-- 1 lukas staff 2780051 28 Apr 18:24 compact_monitor_2_1777389861076.mp4
-rw-r--r-- 1 lukas staff 2715534 28 Apr 18:29 compact_monitor_2_1777390193677.mp4
-rw-r--r-- 1 lukas staff 2102173 28 Apr 18:35 compact_monitor_2_1777390515997.mp4
-rw-r--r-- 1 lukas staff 2324557 28 Apr 18:40 compact_monitor_2_1777390843577.mp4
-rw-r--r-- 1 lukas staff 1525510 28 Apr 18:46 compact_monitor_2_1777391163945.mp4
-rw-r--r-- 1 lukas staff 2776584 28 Apr 18:51 compact_monitor_2_1777391495138.mp4
-rw-r--r-- 1 lukas staff 1168205 28 Apr 18:57 compact_monitor_2_1777391825305.mp4
-rw-r--r-- 1 lukas staff 1736686 28 Apr 19:02 compact_monitor_2_1777392149583.mp4
-rw-r--r-- 1 lukas staff 2133415 28 Apr 19:07 compact_monitor_2_1777392471754.mp4
-rw-r--r-- 1 lukas staff 1289951 28 Apr 19:13 compact_monitor_2_1777392794343.mp4
-rw-r--r-- 1 lukas staff 223494 28 Apr 19:18 compact_monitor_2_1777393110228.mp4
-rw-r--r-- 1 lukas staff 222168 28 Apr 19:23 compact_monitor_2_1777393424109.mp4
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data/2026-04-28 $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data/data $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe/data $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 22523176
drwxr-xr-x 30 lukas staff 960 28 Apr 09:18 .
drwx------+ 93 lukas staff 2976 28 Apr 16:51 ..
-rw-r--r--@ 1 lukas staff 8196 26 Apr 17:14 .DS_Store
drwxr-xr-x 3 lukas staff 96 26 Apr 19:23 .claude
-rw-r--r-- 1 lukas staff 358 16 Apr 16:49 config.json
drwxr-xr-x 167 lukas staff 5344 18 Apr 14:45 data
-rw-r--r--@ 1 lukas staff 11525263360 28 Apr 19:33 db.sqlite
-rw-r--r-- 1 lukas staff 65536 28 Apr 15:26 db.sqlite-shm
-rw-r--r-- 1 lukas staff 2323712 28 Apr 22:23 db.sqlite-wal
drwxr-xr-x 9 lukas staff 288 15 Apr 14:53 pipes
-rw-r--r-- 1 lukas staff 132736 9 Apr 21:27 screenpipe.2026-04-09.0.log
-rw-r--r-- 1 lukas staff 95425 11 Apr 23:14 screenpipe.2026-04-11.0.log
-rw-r--r-- 1 lukas staff 72332 12 Apr 23:55 screenpipe.2026-04-12.0.log
-rw-r--r-- 1 lukas staff 71555 13 Apr 19:50 screenpipe.2026-04-13.0.log
-rw-r--r-- 1 lukas staff 162389 14 Apr 19:31 screenpipe.2026-04-14.0.log
-rw-r--r-- 1 lukas staff 175763 15 Apr 18:55 screenpipe.2026-04-15.0.log
-rw-r--r-- 1 lukas staff 196994 16 Apr 20:33 screenpipe.2026-04-16.0.log
-rw-r--r-- 1 lukas staff 208424 17 Apr 21:06 screenpipe.2026-04-17.0.log
-rw-r--r-- 1 lukas staff 61983 18 Apr 14:45 screenpipe.2026-04-18.0.log
-rw-r--r-- 1 lukas staff 359800 20 Apr 18:52 screenpipe.2026-04-20.0.log
-rw-r--r-- 1 lukas staff 683671 21 Apr 20:18 screenpipe.2026-04-21.0.log
-rw-r--r-- 1 lukas staff 284763 22 Apr 19:10 screenpipe.2026-04-22.0.log
-rw-r--r-- 1 lukas staff 176386 23 Apr 14:01 screenpipe.2026-04-23.0.log
-rw-r--r-- 1 lukas staff 276189 24 Apr 22:35 screenpipe.2026-04-24.0.log
-rw-r--r-- 1 lukas staff 68794 25 Apr 19:40 screenpipe.2026-04-25.0.log
-rw-r--r-- 1 lukas staff 75543 26 Apr 22:56 screenpipe.2026-04-26.0.log
-rw-r--r-- 1 lukas staff 607811 27 Apr 20:42 screenpipe.2026-04-27.0.log
-rw-r--r-- 1 lukas staff 396094 28 Apr 22:23 screenpipe.2026-04-28.0.log
-rwxr-xr-x@ 1 lukas staff 14994 25 Apr 18:50 screenpipe_sync.sh
-rw-r--r--@ 1 lukas staff 34227 26 Apr 17:01 sync.log
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ~/.screenpipe/screenpipe_sync.sh 2026-04-27
[2026-05-06 18:58:18] ========================================
[2026-05-06 18:58:18] Screenpipe sync starting for: 2026-04-27
[2026-05-06 18:58:18] ========================================
[+00m00s] ▶ Preflight checks
Source DB: OK ( 11G)
NAS mount: OK /Volumes/screenpipe
Archive DB: exists (7.7G)
Data dir: OK (242 files, 325M)
[+00m04s] ▶ Counting source rows for 2026-04-27
frames: 7543
elements: 470235
ui_events: 9909
ocr_text: 2193
meetings: 3
[+00m06s] ▶ Initialising tables, indexes, FTS
creating tables ✓ 0m00s
creating indexes ✓ 0m01s
creating FTS tables ✓ 0m00s
[+00m07s] ▶ Syncing data for 2026-04-27
video_chunks ✓ 0m11s
frames (7543 rows) ⠧ Runtime error near line 3: disk I/O error (10)
frames (7543 rows) ⠴ %
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ~/.screenpipe/screenpipe_sync.sh 2026-04-27
[2026-05-06 19:22:16] ========================================
[2026-05-06 19:22:16] Screenpipe sync starting for: 2026-04-27
[2026-05-06 19:22:16] ========================================
[+00m00s] ▶ Preflight checks
Source DB: OK ( 11G)
NAS mount: OK /Volumes/screenpipe
Archive DB: exists (7.7G)
Data dir: OK (242 files, 325M)
[+00m01s] ▶ Counting source rows for 2026-04-27
frames: 7543
elements: 470235
ui_events: 9909
ocr_text: 2193
meetings: 3
[+00m02s] ▶ Initialising tables, indexes, FTS
creating tables ✓ 0m00s
creating indexes ✓ 0m01s
creating FTS tables ✓ 0m00s
[+00m03s] ▶ Syncing data for 2026-04-27
video_chunks ✓ 0m11s
frames (7543 rows) ✓ 4m40s
ocr_text (2193 rows) ✓ 0m25s
ui_events (9909 rows) ✓ 0m02s
elements (470235 rows) ✓ 2m46s
meetings (3 rows) ✓ 0m00s
[+08m07s] ▶ Updating FTS indexes
elements_fts ✓ 2m59s
frames_fts ✓ 6m07s
ui_events_fts ✓ 0m03s
[+17m16s] ▶ Verifying DB
frames: 7543 / 7543 ✓
elements: 470235 / 470235 ✓
ui_events: 9909 / 9909 ✓
ocr_text: 2193 / 2193 ✓
meetings: 3 / 3 ✓
[+18m46s] ▶ Copying data folder for 2026-04-27
rsync 2026-04-27/ → NAS ✓ 0m26s (242 files, 325M)
[2026-05-06 19:41:28] Archive DB size: 9.7G
[2026-05-06 19:41:28] Total time: 19m12s
[2026-05-06 19:41:28] Sync complete for 2026-04-27
[2026-05-06 19:41:28] ========================================
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ~/.screenpipe/screenpipe_sync.sh 2026-04-28
[2026-05-06 19:44:49] ========================================
[2026-05-06 19:44:49] Screenpipe sync starting for: 2026-04-28
[2026-05-06 19:44:49] ========================================
[+00m00s] ▶ Preflight checks
Source DB: OK ( 11G)
NAS mount: OK /Volumes/screenpipe
Archive DB: exists (9.7G)
Data dir: OK (223 files, 159M)
[+00m00s] ▶ Counting source rows for 2026-04-28
frames: 4535
elements: 407532
ui_events: 8621
ocr_text: 1623
meetings: 3
[+00m02s] ▶ Initialising tables, indexes, FTS
creating tables ✓ 0m00s
creating indexes ✓ 0m00s
creating FTS tables ✓ 0m00s
[+00m02s] ▶ Syncing data for 2026-04-28
video_chunks ✓ 0m12s
frames (4535 rows) ✓ 1m30s
ocr_text (1623 rows) ✓ 0m32s
ui_events (8621 rows) ✓ 0m01s
elements (407532 rows) ✓ 1m02s
meetings (3 rows) ✓ 0m00s
[+03m19s] ▶ Updating FTS indexes
elements_fts ✓ 1m36s
frames_fts ✓ 2m28s
ui_events_fts ✓ 0m04s
[+07m27s] ▶ Verifying DB
frames: 4535 / 4535 ✓
elements: 407532 / 407532 ✓
ui_events: 8621 / 8621 ✓
ocr_text: 1623 / 1623 ✓
meetings: 3 / 3 ✓
[+08m59s] ▶ Copying data folder for 2026-04-28
rsync 2026-04-28/ → NAS ✓ 0m20s (223 files, 159M)
[2026-05-06 19:54:08] Archive DB size: 10G
[2026-05-06 19:54:08] Total time: 9m19s
[2026-05-06 19:54:08] Sync complete for 2026-04-28
[2026-05-06 19:54:08] ========================================
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ pkill -f screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ rm -rf ~/.screenpipe/
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 92 lukas staff 2944 6 May 20:22 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd .npm
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ ll
total 24
drwx------ 9 lukas staff 288 28 Apr 09:18 .
drwx------+ 92 lukas staff 2944 6 May 20:22 ..
drwx------ 5 lukas staff 160 1 Nov 2021 _cacache
drwx------@ 2 lukas staff 64 28 Apr 09:18 _locks
drwx------ 15 lukas staff 480 27 Apr 19:54 _logs
drwxr-xr-x 67 lukas staff 2144 28 Apr 09:17 _npx
-rw-r--r--@ 1 lukas staff 0 26 Apr 19:10 _update-notifier-last-checked
-rw-r--r-- 1 lukas staff 173 28 Apr 09:18 anonymous-cli-metrics.json
-rw-r--r-- 1 lukas staff 4764 31 Jan 2024 eresolve-report.txt
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ rm -rf ~/.npm/_npx
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ ll
total 52920
drwx------+ 92 lukas staff 2944 6 May 20:22 .
drwxr-xr-x 5 root admin 160 23 Aug 2024 ..
-r-------- 1 lukas staff 7 18 Nov 2021 .CFUserTextEncoding
-rw-r--r--@ 1 lukas staff 28676 27 Apr 09:11 .DS_Store
drwx------+ 10 lukas staff 320 28 Apr 17:07 .Trash
drwx------ 5 lukas staff 160 1 Nov 2021 .aws
-rw-r--r-- 1 lukas staff 341470 29 Sep 2022 .babel.json
-rw-------@ 1 lukas staff 388 25 Jul 2025 .bash_history
-rw-r--r--@ 1 lukas staff 115 18 Apr 13:19 .bashrc
drwxr-xr-x 5 lukas staff 160 11 Mar 2023 .bito
drwx------@ 6 lukas staff 192 9 Apr 19:53 .cache
drwxr-xr-x 20 lukas staff 640 27 Apr 08:58 .claude
-rw------- 1 lukas staff 28647 27 Apr 09:12 .claude.json
drwxr-xr-x@ 20 lukas staff 640 12 Mar 09:12 .codeium
drwxrwxrwx@ 3 lukas staff 96 2 Mar 2023 .composer
drwx------ 16 lukas staff 512 21 May 2025 .config
drwxr-xr-x 15 lukas staff 480 23 Dec 2024 .continue
drwx------@ 3 lukas staff 96 16 Feb 19:13 .copilot
drwxr-xr-x@ 5 lukas staff 160 9 Apr 2025 .cursor
drwxr-xr-x@ 5 lukas staff 160 17 Aug 2024 .cursor-tutor
drwxr-xr-x 3 lukas staff 96 8 Sep 2024 .daytona
drwxr-xr-x@ 4 lukas staff 128 18 Feb 10:52 .devdb
drwx------ 24 lukas staff 768 27 Apr 18:14 .docker
drwx------ 15 lukas staff 480 6 Jun 2023 .dropbox
drwxr-xr-x@ 3 lukas staff 96 20 Nov 2022 .fig.dotfiles.bak
-rw-r--r-- 1 lukas staff 138 5 Mar 2022 .gauth
-rw-r--r-- 1 lukas staff 220 25 Nov 2021 .gitconfig
-rw-r--r-- 1 lukas staff 12288 25 Nov 2021 .gitconfig.swp
drwx------ 5 lukas staff 160 18 Nov 2021 .hammerspoon
drwxr-xr-x 3 lukas staff 96 21 Mar 2025 .idlerc
-rw------- 1 lukas staff 20 28 Apr 16:51 .lesshst
drwx------ 5 lukas staff 160 23 Dec 2024 .local
-rw------- 1 lukas staff 204 16 Mar 2024 .netrc
drwx------ 3 lukas staff 96 1 Nov 2021 .node-gyp
-rw------- 1 lukas staff 4 6 Feb 2024 .node_repl_history
-rw-r--r-- 1 lukas staff 17 24 Dec 2023 .notion-enhancer
drwxr-xr-x 4 lukas staff 128 12 Jul 2024 .notion-py
drwx------ 8 lukas staff 256 6 May 20:24 .npm
-rw------- 1 lukas staff 74 20 May 2024 .npmrc
drwx------ 32 lukas staff 1024 25 Jul 2025 .nvm
drwxr-xr-x 4 lukas staff 128 5 Aug 2023 .postman
-rw-r--r--@ 1 lukas staff 77 9 Feb 2023 .profile
-rw-------@ 1 lukas staff 3153 21 Mar 2025 .python_history
drwx------ 2 lukas staff 64 15 Nov 2021 .quicktype-vscode
drwxr-xr-x@ 8 lukas staff 256 16 Feb 08:48 .redis-insight
drwxr-xr-x 4 lukas staff 128 4 Feb 09:35 .sonarlint
drwx------ 15 lukas staff 480 8 Aug 2025 .ssh
drwxr-xr-x@ 3 lukas staff 96 15 Aug 2025 .streamlit
drwx------ 6 lukas staff 192 17 Oct 2022 .swiftpm
-rw------- 1 lukas staff 12143 27 Apr 14:58 .viminfo
drwx------ 5 lukas staff 160 19 Jun 2023 .vscode
drwxr-xr-x@ 3 lukas staff 96 20 Jan 2025 .warp
UW PICO 5.09 New Buffer
[ Read 1 line ]
^G Get Help ^O WriteOut ^R Read File ^Y Prev Pg ^K Cut Text ^C Cur Pos
^X Exit ^J Justify ^W Where is ^V Next Pg ^U UnCut Text ^T To Spell
drwxr-xr-x 4 lukas staff 128 29 Apr 2023 .wdm
drwxr-xr-x@ 5 lukas staff 160 26 Jan 13:03 .windsurf
drwxr-xr-x 4 lukas staff 128 24 Mar 12:03 .yarn
-rw-r--r-- 1 lukas staff 116 30 Mar 10:12 .yarnrc
-rw-r--r-- 1 lukas staff 49518 21 Apr 09:09 .zcompdump
-rw-r--r--@ 1 lukas staff 46758 2 Nov 2025 .zcompdump.Lukas-Kovaliks-MacBook-Pro-Jiminny.23381
-rw-r--r--@ 1 lukas staff 6116 20 Apr 19:52 .zprofile
-rw-r--r-- 1 lukas staff 1468 8 Apr 2022 .zprofile-copy
-rw-r--r--@ 1 lukas staff 2900 15 Mar 2023 .zprofile.pysave
-rw------- 1 lukas staff 1731 29 Jun 2022 .zprofile.save
-rw-r--r-- 1 lukas staff 1569 8 Apr 2022 .zprofilees
-rw------- 1 lukas staff 50310 28 Apr 11:32 .zsh_history
drwx------ 9 lukas staff 288 6 May 2025 .zsh_sessions
-rw-r--r--@ 1 lukas staff 400 18 Apr 13:19 .zshrc
drwx------@ 9 lukas staff 288 20 Apr 20:55 Applications
drwxr-xr-x@ 2 lukas staff 64 22 Oct 2025 CascadeProjects
drwxr-xr-x 4 lukas staff 128 27 Oct 2025 DEV
drwx------@ 10 lukas staff 320 28 Apr 18:52 Desktop
drwx------@ 7 lukas staff 224 26 Mar 14:40 Documents
drwx------@ 44 lukas staff 1408 24 Apr 16:53 Downloads
drwxr-xr-x@ 4 lukas staff 128 17 Mar 20:27 Keychron_Screen
drwx------@ 112 lukas staff 3584 2 Dec 09:19 Library
drwx------ 7 lukas staff 224 12 Feb 2024 Movies
drwx------+ 5 lukas staff 160 25 Sep 2023 Music
drwx------+ 9 lukas staff 288 25 Sep 2023 Pictures
drwx------ 3 lukas staff 96 8 Nov 2021 Postman
drwx------+ 4 lukas staff 128 28 Oct 2021 Public
-rw-r--r--@ 1 lukas staff 3950 15 Dec 09:16 Untitled 4.spf
drwx------ 4 lukas staff 128 2 Jul 2023 Users
-rw-r--r-- 1 lukas staff 17050804 27 Apr 19:18 cleanshot-live.log
-rw-r--r-- 1 lukas staff 9363061 27 Apr 19:24 cleanshot-screenpipe.log
-rw-r--r-- 1 lukas staff 0 12 Apr 12:50 clip.mp4
-rw-r--r-- 1 lukas staff 0 12 Apr 12:51 frame.jpg
drwx------ 3 lukas staff 96 30 Sep 2022 iCloud Drive (Archive)
drwx------ 16 lukas staff 512 3 Nov 2025 jiminny
drwxr-xr-x 3 lukas staff 96 20 Mar 18:47 node_modules
drwxr-xr-x 4 lukas staff 128 21 Oct 2025 raycast
-rw-r--r-- 1 lukas staff 0 1 Mar 14:26 response.bin
-rwxr-xr-x 1 lukas staff 3824 11 Apr 15:16 screenpipe-day.sh
-rw-r--r-- 1 lukas staff 86 20 Mar 18:47 yarn.lock
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
cd: no such file or directory: /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ touch screenpipe_sync.sh
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ nano screenpipe_sync.sh
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ npx screenpipe@latest record --ignored-windows "Boosteroid" --retention-days 7
detected hardware tier: Mid
warning: parakeet is not supported on this platform, using whisper-tiny instead
2026-05-06T20:27:32.721416Z INFO screenpipe_engine::auth_key: api auth: key resolved via auto-generated
checking permissions...
screen recording: ok
microphone: ok
accessibility: ok
2026-05-06T20:27:32.831033Z INFO screenpipe_screen::monitor::macos_version: Detected macOS version: 14.6
2026-05-06T20:27:34.088403Z INFO screenpipe_engine::sleep_monitor: Starting macOS sleep/wake monitor
2026-05-06T20:27:34.089942Z INFO screenpipe_engine::sleep_monitor: Screen lock/unlock observers registered (CFNotificationCenter)
2026-05-06T20:27:34.090417Z INFO screenpipe_engine::sleep_monitor: Display reconfiguration watcher registered (CGDisplayRegisterReconfigurationCallback)
2026-05-06T20:27:34.112650Z INFO screenpipe_engine::permission_monitor: permission monitor started screen=true mic=true accessibility=true keychain=true
2026-05-06T20:27:34.112711Z INFO screenpipe: meeting detector enabled — independent of transcription mode
2026-05-06T20:27:34.619906Z INFO screenpipe: API server listening on [IP_ADDRESS]:3030 (localhost only)
2026-05-06T20:27:34.619937Z INFO screenpipe: API auth enabled — run `screenpipe auth token` to view your key
2026-05-06T20:27:34.619857Z INFO screenpipe_engine::snapshot_compaction: snapshot compaction worker started (min_age=600s, poll=300s)
2026-05-06T20:27:34.619847Z INFO screenpipe_engine::power::manager: power manager started (poll interval: 10s)
2026-05-06T20:27:34.620018Z INFO screenpipe_engine::vision_manager::manager: Starting VisionManager
2026-05-06T20:27:34.624746Z INFO screenpipe_core::pipes: installed built-in pipe: day-recap
2026-05-06T20:27:34.626304Z INFO screenpipe_core::pipes: installed built-in pipe: standup-update
2026-05-06T20:27:34.628597Z INFO screenpipe_core::pipes: installed built-in pipe: ai-habits
2026-05-06T20:27:34.629463Z INFO screenpipe_core::pipes: installed built-in pipe: time-breakdown
2026-05-06T20:27:34.630081Z INFO screenpipe_core::pipes: installed built-in pipe: video-export
2026-05-06T20:27:34.630972Z INFO screenpipe_core::pipes: installed built-in pipe: meeting-summary
2026-05-06T20:27:34.631427Z INFO screenpipe_core::pipes: loaded pipe: day-recap
2026-05-06T20:27:34.631521Z INFO screenpipe_core::pipes: loaded pipe: standup-update
2026-05-06T20:27:34.631587Z INFO screenpipe_core::pipes: loaded pipe: ai-habits
2026-05-06T20:27:34.631640Z INFO screenpipe_core::pipes: loaded pipe: time-breakdown
2026-05-06T20:27:34.631690Z INFO screenpipe_core::pipes: loaded pipe: video-export
2026-05-06T20:27:34.631738Z INFO screenpipe_core::pipes: loaded pipe: meeting-summary
2026-05-06T20:27:34.631752Z INFO screenpipe_core::pipes: loaded 6 pipes from "/Users/lukas/.screenpipe/pipes"
_
__________________ ___ ____ ____ (_____ ___
/ ___/ ___/ ___/ _ \/ _ \/ __ \ / __ \/ / __ \/ _ \
(__ / /__/ / / __/ __/ / / / / /_/ / / /_/ / __/
/____/\___/_/ \___/\___/_/ /_/ / .___/_/ .___/\___/
/_/ /_/
power AI by everything you've seen, said or heard
open source | runs locally | developer friendly
┌────────────────────────┬────────────────────────────────────┐
│ setting │ value │
├────────────────────────┼────────────────────────────────────┤
│ audio chunk duration │ 30 seconds │
│ port │ 3030 │
│ audio disabled │ false │
│ vision disabled │ false │
│ pause on DRM content │ false │
│ audio engine │ Parakeet │
│ vad engine │ Silero │
│ data directory │ /Users/lukas/.screenpipe │
│ debug mode │ false │
│ telemetry │ true │
│ use pii removal │ true │
│ use all monitors │ true │
│ ignored windows │ ["Boosteroid"] │
│ included windows │ [] │
│ cloud sync │ disabled │
│ auto-destruct pid │ 0 │
│ deepgram key │ not set │
│ api auth │ enabled │
│ encrypt secrets │ disabled │
│ retention days │ 7 │
│ retention mode │ media-only (keep transcripts) │
├────────────────────────┼────────────────────────────────────┤
│ languages │ │
│ │ all languages │
├────────────────────────┼────────────────────────────────────┤
│ monitors │ │
│ │ id: 1 │
│ │ id: 2 │
├────────────────────────┼────────────────────────────────────┤
│ audio devices │ │
│ │ MacBook Pro Microphone (input) │
│ │ System Audio (output) │
└────────────────────────┴────────────────────────────────────┘
you are using local processing. all your data stays on your computer.
warning: telemetry is enabled. only error-level data will be sent.
to disable, use the --disable-telemetry flag.
check latest changes here: https://github.com/screenpipe/screenpipe/releases
2026-05-06T20:27:34.638384Z INFO screenpipe: starting UI event capture
2026-05-06T20:27:34.637679Z INFO screenpipe_core::pipes: pipe scheduler started (generation 2)
2026-05-06T20:27:34.649154Z INFO screenpipe_engine::power::manager: initial power profile: Performance (on_ac=true, battery=Some(94))
2026-05-06T20:27:34.652794Z WARN screenpipe: pi agent install failed: bun not found — install from https://bun.sh
2026-05-06T20:27:34.655839Z INFO screenpipe_engine::ui_recorder: Starting UI event capture
2026-05-06T20:27:34.673877Z INFO screenpipe_engine::ui_recorder: UI recording session started: 54869993-7b4b-491f-b717-2a583517f9c5
2026-05-06T20:27:34.673910Z INFO screenpipe_engine::calendar_speaker_id: speaker identification: started (user_name=<not set>)
2026-05-06T20:27:34.674057Z INFO screenpipe_engine::hot_frame_cache: hot_frame_cache: warming from DB (2026-05-05 17:27:34.674056 UTC to 2026-05-06 17:27:34.674056 UTC)
2026-05-06T20:27:34.674892Z INFO screenpipe_engine::meeting_detector: meeting v2: detection loop started (base_interval=5s, profiles=12)
2026-05-06T20:27:34.675788Z INFO screenpipe_engine::hot_frame_cache: hot_frame_cache: warmed with 0 frame entries, coverage from 2026-05-05 17:27:34.674056 UTC
2026-05-06T20:27:34.686546Z INFO screenpipe_engine::server: Server listening on [IP_ADDRESS]:3030
2026-05-06T20:27:34.691371Z INFO screenpipe_connect::mdns: mdns: advertising screenpipe on port 3030
2026-05-06T20:27:36.270608Z INFO screenpipe_engine::vision_manager::manager: Starting vision recording for monitor 1 (1440x900)
2026-05-06T20:27:36.270669Z INFO screenpipe_engine::vision_manager::manager: Starting event-driven capture for monitor 1 (device: monitor_1)
2026-05-06T20:27:36.270714Z INFO screenpipe_engine::event_driven_capture: event-driven capture started for monitor 1 (device: monitor_1)
2026-05-06T20:27:36.932583Z INFO screenpipe_engine::vision_manager::manager: Starting vision recording for monitor 2 (3008x1253)
2026-05-06T20:27:36.932852Z INFO screenpipe_engine::vision_manager::manager: Starting event-driven capture for monitor 2 (device: monitor_2)
2026-05-06T20:27:36.932882Z INFO screenpipe_engine::vision_manager::manager: VisionManager started with 2/2 monitor(s)
2026-05-06T20:27:36.932899Z INFO screenpipe_engine::vision_manager::monitor_watcher: Starting monitor watcher (event-driven via CGDisplayRegisterReconfigurationCallback, 60s backstop poll)
2026-05-06T20:27:36.932901Z INFO screenpipe_engine::event_driven_capture: event-driven capture started for monitor 2 (device: monitor_2)
2026-05-06T20:27:39.158281Z INFO sck_rs::stream_manager: persistent SCK stream started for display 1 (1440x900, 2fps, 3 excluded)
2026-05-06T20:27:39.593177Z INFO screenpipe_engine::event_driven_capture: startup capture for monitor 1: frame_id=1, dur=101ms
2026-05-06T20:27:40.672366Z INFO sck_rs::stream_manager: persistent SCK stream started for display 2 (3008x1253, 2fps, 3 excluded)
2026-05-06T20:27:41.257664Z INFO screenpipe_engine::event_driven_capture: startup capture for monitor 2: frame_id=2, dur=140ms
2026-05-06T20:27:44.641022Z INFO screenpipe_audio::transcription::engine: whisper model available: "/Users/lukas/.cache/huggingface/hub/models--ggerganov--whisper.cpp/snapshots/5359861c739e955e79d9a303bcbc70fb988958b1/ggml-tiny.bin"
2026-05-06T20:27:44.641079Z INFO screenpipe_audio::transcription::whisper::model: whisper context: gpu acceleration enabled (Metal on macOS, Vulkan on Windows)
2026-05-06T20:27:44.641086Z INFO screenpipe_audio::transcription::engine: loading whisper model with GPU acceleration...
whisper_init_from_file_with_params_no_state: loading model from '/Users/lukas/.cache/huggingface/hub/models--ggerganov--whisper.cpp/snapshots/5359861c739e955e79d9a303bcbc70fb988958b1/ggml-tiny.bin'
whisper_init_with_params_no_state: use gpu = 1
whisper_init_with_params_no_state: flash attn = 0
whisper_init_with_params_no_state: gpu_device = 0
whisper_init_with_params_no_state: dtw = 0
ggml_metal_device_init: tensor API disabled for pre-M5 and pre-A19 devices
ggml_metal_library_init: using embedded metal library
ggml_metal_library_init: loaded in 0.041 sec
ggml_metal_rsets_init: creating a residency set collection (keep_alive = 180 s)
ggml_metal_device_init: GPU name: Apple M1
ggml_metal_device_init: GPU family: MTLGPUFamilyApple7 (1007)
ggml_metal_device_init: GPU family: MTLGPUFamilyCommon3 (3003)
ggml_metal_device_init: GPU family: MTLGPUFamilyMetal3 (5001)
ggml_metal_device_init: simdgroup reduction = true
ggml_metal_device_init: simdgroup matrix mul. = true
ggml_metal_device_init: has unified memory = true
ggml_metal_device_init: has bfloat = true
ggml_metal_device_init: has tensor = false
ggml_metal_device_init: use residency sets = true
ggml_metal_device_init: use shared buffers = true
ggml_metal_device_init: recommendedMaxWorkingSetSize = 11453.25 MB
whisper_init_with_params_no_state: devices = 3
whisper_init_with_params_no_state: backends = 3
whisper_model_load: loading model
whisper_model_load: n_vocab = 51865
whisper_model_load: n_audio_ctx = 1500
whisper_model_load: n_audio_state = 384
whisper_model_load: n_audio_head = 6
whisper_model_load: n_audio_layer = 4
whisper_model_load: n_text_ctx = 448
whisper_model_load: n_text_state = 384
whisper_model_load: n_text_head = 6
whisper_model_load: n_text_layer = 4
whisper_model_load: n_mels = 80
whisper_model_load: ftype = 1
whisper_model_load: qntvr = 0
whisper_model_load: type = 1 (tiny)
whisper_model_load: adding 1608 extra tokens
whisper_model_load: n_langs = 99
whisper_model_load: Metal total size = 77.11 MB
whisper_model_load: model size = 77.11 MB
2026-05-06T20:27:44.857210Z INFO screenpipe_audio::transcription::engine: whisper model loaded successfully
whisper_backend_init_gpu: device 0: Metal (type: 1)
whisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)
whisper_backend_init_gpu: using Metal backend
ggml_metal_init: allocating
ggml_metal_init: found device: Apple M1
ggml_metal_init: picking default device: Apple M1
ggml_metal_init: use fusion = true
ggml_metal_init: use concurrency = true
ggml_metal_init: use graph optimize = true
whisper_backend_init: using BLAS backend
whisper_init_state: kv self size = 3.15 MB
whisper_init_state: kv cross size = 9.44 MB
whisper_init_state: kv pad size = 2.36 MB
whisper_init_state: compute buffer (conv) = 14.17 MB
whisper_init_state: compute buffer (encode) = 65.96 MB
whisper_init_state: compute buffer (cross) = 8.50 MB
whisper_init_state: compute buffer (decode) = 96.83 MB
2026-05-06T20:27:44.861912Z INFO screenpipe_audio::audio_manager::manager: transcription session created (will be reused across segments)
2026-05-06T20:27:44.862480Z INFO screenpipe_audio::audio_manager::manager: audio manager started
2026-05-06T20:27:44.862525Z INFO screenpipe_audio::audio_manager::manager: calendar-assisted speaker diarization: listening for meeting events
2026-05-06T20:27:47.831980Z INFO screenpipe_audio::device::device_manager: starting recording for device: System Audio (output)
2026-05-06T20:27:47.832191Z INFO screenpipe_audio::core::run_record_and_transcribe: starting continuous recording for System Audio (output) (unknown / 30s segments)
2026-05-06T20:27:47.906029Z INFO screenpipe_audio::device::device_manager: starting recording for device: MacBook Pro Microphone (input)
2026-05-06T20:27:47.906090Z INFO screenpipe_audio::core::run_record_and_transcribe: starting continuous recording for MacBook Pro Microphone (input) (wired / 30s segments)
2026-05-06T20:28:15.251258Z INFO screenpipe_engine::event_driven_capture: content dedup: skipping capture for monitor 1 (hash=-8608554010568040663, trigger=visual_change)
whisper_backend_init_gpu: device 0: Metal (type: 1)
whisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)
whisper_backend_init_gpu: using Metal backend
ggml_metal_init: allocating
ggml_metal_init: found device: Apple M1
ggml_metal_init: picking default device: Apple M1
ggml_metal_init: use fusion = true
ggml_metal_init: use concurrency = true
ggml_metal_init: use graph optimize = true
whisper_backend_init: using BLAS backend
whisper_init_state: kv self size = 3.15 MB
whisper_init_state: kv cross size = 9.44 MB
whisper_init_state: kv pad size = 2.36 MB
whisper_init_state: compute buffer (conv) = 14.17 MB
whisper_init_state: compute buffer (encode) = 65.96 MB
whisper_init_state: compute buffer (cross) = 8.50 MB
whisper_init_state: compute buffer (decode) = 96.83 MB
ggml_metal_free: deallocating
whisper_backend_init_gpu: device 0: Metal (type: 1)
whisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)
whisper_backend_init_gpu: using Metal backend
ggml_metal_init: allocating
ggml_metal_init: found device: Apple M1
ggml_metal_init: picking default device: Apple M1
ggml_metal_init: use fusion = true
ggml_metal_init: use concurrency = true
ggml_metal_init: use graph optimize = true
whisper_backend_init: using BLAS backend
whisper_init_state: kv self size = 3.15 MB
whisper_init_state: kv cross size = 9.44 MB
whisper_init_state: kv pad size = 2.36 MB
whisper_init_state: compute buffer (conv) = 14.17 MB
whisper_init_state: compute buffer (encode) = 65.96 MB
whisper_init_state: compute buffer (cross) = 8.50 MB
whisper_init_state: compute buffer (decode) = 96.83 MB
ggml_metal_free: deallocating
whisper_backend_init_gpu: device 0: Metal (type: 1)
whisper_backend_init_gpu: found GPU device 0: Metal (type: 1, cnt: 0)
whisper_backend_init_gpu: using Metal backend
ggml_metal_init: allocating
ggml_metal_init: found device: Apple M1
ggml_metal_init: picking default device: Apple M1
ggml_metal_init: use fusion = true
ggml_metal_init: use concurrency = true
ggml_metal_init: use graph optimize = true
whisper_backend_init: using BLAS backend
whisper_init_state: kv self size = 3.15 MB
whisper_init_state: kv cross size = 9.44 MB
whisper_init_state: kv pad size = 2.36 MB
whisper_init_state: compute buffer (conv) = 14.17 MB
whisper_init_state: compute buffer (encode) = 65.96 MB
whisper_init_state: compute buffer (cross) = 8.50 MB
whisper_init_state: compute buffer (decode) = 96.83 ...
|
iTerm2
|
screenpipe"
|
NULL
|
|
rsync 2026-04-27/ → NAS ✓ 0m26s (242 f rsync 2026-04-27/ → NAS ✓ 0m26s (242 files, 325M)
[2026-05-06 19:41:28] Archive DB size: 9.7G
[2026-05-06 19:41:28] Total time: 19m12s
[2026-05-06 19:41:28] Sync complete for 2026-04-27
[2026-05-06 19:41:28] ========================================
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ~/.screenpipe/screenpipe_sync.sh 2026-04-28
[2026-05-06 19:44:49] ========================================
[2026-05-06 19:44:49] Screenpipe sync starting for: 2026-04-28
[2026-05-06 19:44:49] ========================================
[+00m00s] ▶ Preflight checks
Source DB: OK ( 11G)
NAS mount: OK /Volumes/screenpipe
Archive DB: exists (9.7G)
Data dir: OK (223 files, 159M)
[+00m00s] ▶ Counting source rows for 2026-04-28
frames: 4535
elements: 407532
ui_events: 8621
ocr_text: 1623
meetings: 3
[+00m02s] ▶ Initialising tables, indexes, FTS
creating tables ✓ 0m00s
creating indexes ✓ 0m00s
creating FTS tables ✓ 0m00s
[+00m02s] ▶ Syncing data for 2026-04-28
video_chunks ✓ 0m12s
frames (4535 rows) ✓ 1m30s
ocr_text (1623 rows) ✓ 0m32s
ui_events (8621 rows) ✓ 0m01s
elements (407532 rows) ✓ 1m02s
meetings (3 rows) ✓ 0m00s
[+03m19s] ▶ Updating FTS indexes
elements_fts ✓ 1m36s
frames_fts ✓ 2m28s
ui_events_fts ✓ 0m04s
[+07m27s] ▶ Verifying DB
frames: 4535 / 4535 ✓
elements: 407532 / 407532 ✓
ui_events: 8621 / 8621 ✓
ocr_text: 1623 / 1623 ✓
meetings: 3 / 3 ✓
[+08m59s] ▶ Copying data folder for 2026-04-28
rsync 2026-04-28/ → NAS ✓ 0m20s (223 files, 159M)
[2026-05-06 19:54:08] Archive DB size: 10G
[2026-05-06 19:54:08] Total time: 9m19s
[2026-05-06 19:54:08] Sync complete for 2026-04-28
[2026-05-06 19:54:08] ========================================
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cat screenpipe_sync.sh
#!/bin/bash
# screenpipe_sync.sh
# Syncs Screenpipe SQLite data to a NAS archive database (append-only, no deletions).
# Also copies the day's video/frame data folder to the NAS.
#
# Usage:
# ./screenpipe_sync.sh # syncs yesterday (default)
# ./screenpipe_sync.sh 2026-04-15 # syncs a specific date
# ./screenpipe_sync.sh today # syncs today so far
#
# Cron example (runs at 3am daily):
# 0 3 * * * /Users/lukas/.screenpipe/screenpipe_sync.sh >> /Users/lukas/.screenpipe/sync.log 2>&1
set -euo pipefail
# ─── CONFIG ───────────────────────────────────────────────────────────────────
DB_SRC="${SCREENPIPE_DB:-$HOME/.screenpipe/db.sqlite}"
NAS_MOUNT="${NAS_MOUNT:-/Volumes/screenpipe}"
NAS_DB="$NAS_MOUNT/archive.db"
NAS_DATA="$NAS_MOUNT/data"
LOG_FILE="$HOME/.screenpipe/sync.log"
# ──────────────────────────────────────────────────────────────────────────────
# ─── HELPERS ──────────────────────────────────────────────────────────────────
SCRIPT_START=$(date +%s)
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
echo "$msg" | tee -a "$LOG_FILE"
}
step() {
local now=$(date +%s)
local elapsed=$(( now - SCRIPT_START ))
local min=$(( elapsed / 60 ))
local sec=$(( elapsed % 60 ))
printf "\n[+%02dm%02ds] ▶ %s\n" "$min" "$sec" "$*" | tee -a "$LOG_FILE"
}
run_sqlite_heredoc() {
local label="$1"
local sql="$2"
local start=$(date +%s)
printf " %-36s " "$label"
sqlite3 "$DB_SRC" <<< "$sql" &
local pid=$!
local spin=[PASSWORD] '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r %-36s %s " "$label" "${spin[$i]}"
i=$(( (i + 1) % 10 ))
sleep 0.2
done
wait "$pid"
local rc=$?
if [ $rc -ne 0 ]; then
printf "\r %-36s ✗ FAILED\n" "$label" | tee -a "$LOG_FILE"
exit $rc
fi
local dur=$(( $(date +%s) - start ))
printf "\r %-36s ✓ %dm%02ds\n" "$label" "$(( dur / 60 ))" "$(( dur % 60 ))" | tee -a "$LOG_FILE"
}
check() {
local label="$1" got="$2" expected="$3"
if [ "$got" -eq "$expected" ]; then
printf " %-20s %s / %s ✓\n" "$label:" "$got" "$expected"
else
printf " %-20s %s / %s ✗ MISMATCH\n" "$label:" "$got" "$expected"
fi
}
# ──────────────────────────────────────────────────────────────────────────────
# ─── DATE ARGUMENT ────────────────────────────────────────────────────────────
if [ "${1:-}" = "today" ]; then
TARGET_DATE=$(date +%Y-%m-%d)
elif [ -n "${1:-}" ]; then
TARGET_DATE="$1"
if ! [[ "$TARGET_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid date format. Use YYYY-MM-DD, 'today', or no argument for yesterday."
exit 1
fi
else
TARGET_DATE=$(date -v-1d +%Y-%m-%d)
fi
log "========================================"
log "Screenpipe sync starting for: $TARGET_DATE"
log "========================================"
# ─── PREFLIGHT ────────────────────────────────────────────────────────────────
step "Preflight checks"
if [ ! -f "$DB_SRC" ]; then
log "ERROR: Source DB not found at $DB_SRC"; exit 1
fi
printf " %-20s %s (%s)\n" "Source DB:" "OK" "$(du -sh "$DB_SRC" | cut -f1)"
if [ ! -d "$NAS_MOUNT" ]; then
log "ERROR: NAS not mounted at $NAS_MOUNT"; exit 1
fi
printf " %-20s %s\n" "NAS mount:" "OK $NAS_MOUNT"
# Check if DB already synced for this date
DB_ALREADY_SYNCED=false
if [ -f "$NAS_DB" ]; then
EXISTING=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';" 2>/dev/null || echo "0")
if [ "$EXISTING" -gt "0" ]; then
log "Date $TARGET_DATE already has $EXISTING frames in archive — skipping DB sync"
DB_ALREADY_SYNCED=true
else
printf " %-20s %s (%s)\n" "Archive DB:" "exists" "$(du -sh "$NAS_DB" | cut -f1)"
fi
else
printf " %-20s %s\n" "Archive DB:" "will be created"
fi
# Source data dir for this date
DATA_SRC="$HOME/.screenpipe/data/data/$TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
DATA_SIZE=$(du -sh "$DATA_SRC" | cut -f1)
DATA_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
printf " %-20s %s (%s files, %s)\n" "Data dir:" "OK" "$DATA_FILES" "$DATA_SIZE"
else
printf " %-20s %s\n" "Data dir:" "not found — skipping file copy"
fi
# ─── DB SYNC ──────────────────────────────────────────────────────────────────
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── COUNT SOURCE ROWS ────────────────────────────────────────────────────
step "Counting source rows for $TARGET_DATE"
SRC_FRAMES=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
SRC_ELEMENTS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_UI=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
SRC_OCR=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
SRC_MEETINGS=$(sqlite3 "$DB_SRC" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start) = '$TARGET_DATE';")
printf " %-20s %s\n" "frames:" "$SRC_FRAMES"
printf " %-20s %s\n" "elements:" "$SRC_ELEMENTS"
printf " %-20s %s\n" "ui_events:" "$SRC_UI"
printf " %-20s %s\n" "ocr_text:" "$SRC_OCR"
printf " %-20s %s\n" "meetings:" "$SRC_MEETINGS"
if [ "$SRC_FRAMES" -eq "0" ]; then
log "No frames found for $TARGET_DATE — skipping DB sync"
DB_ALREADY_SYNCED=true
fi
fi
if [ "$DB_ALREADY_SYNCED" = false ]; then
# ─── INIT TABLES ──────────────────────────────────────────────────────────
step "Initialising tables, indexes, FTS"
run_sqlite_heredoc "creating tables" "
ATTACH '$NAS_DB' AS nas;
CREATE TABLE IF NOT EXISTS nas.frames AS SELECT * FROM main.frames WHERE 0;
CREATE TABLE IF NOT EXISTS nas.elements AS SELECT * FROM main.elements WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ui_events AS SELECT * FROM main.ui_events WHERE 0;
CREATE TABLE IF NOT EXISTS nas.ocr_text AS SELECT * FROM main.ocr_text WHERE 0;
CREATE TABLE IF NOT EXISTS nas.video_chunks AS SELECT * FROM main.video_chunks WHERE 0;
CREATE TABLE IF NOT EXISTS nas.meetings AS SELECT * FROM main.meetings WHERE 0;
DETACH nas;
"
run_sqlite_heredoc "creating indexes" "
ATTACH '$NAS_DB' AS nas;
CREATE INDEX IF NOT EXISTS nas.idx_frames_timestamp ON frames(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_frames_app_name ON frames(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_window_name ON frames(window_name);
CREATE INDEX IF NOT EXISTS nas.idx_frames_video_chunk_id ON frames(video_chunk_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_id ON elements(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_elements_frame_src_role ON elements(frame_id, source, role) WHERE text IS NOT NULL;
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_timestamp ON ui_events(timestamp);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_app_name ON ui_events(app_name);
CREATE INDEX IF NOT EXISTS nas.idx_ui_events_frame_id ON ui_events(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_ocr_text_frame_id ON ocr_text(frame_id);
CREATE INDEX IF NOT EXISTS nas.idx_meetings_start ON meetings(meeting_start);
CREATE INDEX IF NOT EXISTS nas.idx_video_chunks_device ON video_chunks(device_name);
DETACH nas;
"
run_sqlite_heredoc "creating FTS tables" "
ATTACH '$NAS_DB' AS nas;
CREATE VIRTUAL TABLE IF NOT EXISTS nas.elements_fts USING fts5(
text, role, frame_id UNINDEXED,
content='elements', content_rowid='id', tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.frames_fts USING fts5(
full_text, app_name, window_name, browser_url, id UNINDEXED,
tokenize='unicode61'
);
CREATE VIRTUAL TABLE IF NOT EXISTS nas.ui_events_fts USING fts5(
text_content,
app_name,
window_title,
element_name,
content='ui_events',
content_rowid='id',
tokenize='unicode61'
);
DETACH nas;
"
# ─── SYNC DATA ────────────────────────────────────────────────────────────
step "Syncing data for $TARGET_DATE"
run_sqlite_heredoc "video_chunks" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.video_chunks
SELECT * FROM main.video_chunks
WHERE id IN (
SELECT DISTINCT video_chunk_id FROM main.frames
WHERE date(timestamp) = '$TARGET_DATE' AND video_chunk_id IS NOT NULL
);
DETACH nas;
"
run_sqlite_heredoc "frames ($SRC_FRAMES rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.frames
SELECT * FROM main.frames WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ocr_text ($SRC_OCR rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ocr_text
SELECT o.* FROM main.ocr_text o
JOIN main.frames f ON o.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "ui_events ($SRC_UI rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.ui_events
SELECT * FROM main.ui_events WHERE date(timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "elements ($SRC_ELEMENTS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.elements
SELECT e.* FROM main.elements e
JOIN main.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE';
DETACH nas;
"
run_sqlite_heredoc "meetings ($SRC_MEETINGS rows)" "
ATTACH '$NAS_DB' AS nas;
INSERT OR IGNORE INTO nas.meetings
SELECT * FROM main.meetings WHERE date(meeting_start) = '$TARGET_DATE';
DETACH nas;
"
# ─── FTS UPDATE ───────────────────────────────────────────────────────────
step "Updating FTS indexes"
run_sqlite_heredoc "elements_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.elements_fts(rowid, text, role)
SELECT e.id, e.text, e.role
FROM nas.elements e
JOIN nas.frames f ON e.frame_id = f.id
WHERE date(f.timestamp) = '$TARGET_DATE'
AND e.text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "frames_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.frames_fts(rowid, full_text, app_name, window_name, browser_url, id)
SELECT id, full_text, app_name, window_name, browser_url, id
FROM nas.frames
WHERE date(timestamp) = '$TARGET_DATE'
AND full_text IS NOT NULL;
DETACH nas;
"
run_sqlite_heredoc "ui_events_fts" "
ATTACH '$NAS_DB' AS nas;
INSERT INTO nas.ui_events_fts(rowid, text_content, app_name, window_title, element_name)
SELECT id, text_content, app_name, window_title, element_name
FROM nas.ui_events
WHERE date(timestamp) = '$TARGET_DATE'
AND text_content IS NOT NULL;
DETACH nas;
"
# ─── VERIFY DB ────────────────────────────────────────────────────────────
step "Verifying DB"
V_FRAMES=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM frames WHERE date(timestamp) = '$TARGET_DATE';")
V_ELEMENTS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM elements WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_UI=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ui_events WHERE date(timestamp) = '$TARGET_DATE';")
V_OCR=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM ocr_text WHERE frame_id IN (SELECT id FROM frames WHERE date(timestamp) = '$TARGET_DATE');")
V_MEETINGS=$(sqlite3 "$NAS_DB" "SELECT COUNT(*) FROM meetings WHERE date(meeting_start)= '$TARGET_DATE';")
check "frames" "$V_FRAMES" "$SRC_FRAMES"
check "elements" "$V_ELEMENTS" "$SRC_ELEMENTS"
check "ui_events" "$V_UI" "$SRC_UI"
check "ocr_text" "$V_OCR" "$SRC_OCR"
check "meetings" "$V_MEETINGS" "$SRC_MEETINGS"
fi
# ─── COPY DATA FOLDER ─────────────────────────────────────────────────────────
# Always runs regardless of DB sync status
step "Copying data folder for $TARGET_DATE"
if [ -d "$DATA_SRC" ]; then
mkdir -p "$NAS_DATA/$TARGET_DATE"
RSYNC_START=$(date +%s)
printf " %-36s " "rsync $TARGET_DATE/ → NAS"
rsync -a --ignore-existing \
"$DATA_SRC/" \
"$NAS_DATA/$TARGET_DATE/" \
2>>"$LOG_FILE"
RSYNC_DUR=$(( $(date +%s) - RSYNC_START ))
COPIED_FILES=$(ls "$NAS_DATA/$TARGET_DATE" | wc -l | tr -d ' ')
SRC_FILES=$(ls "$DATA_SRC" | wc -l | tr -d ' ')
COPIED_SIZE=$(du -sh "$NAS_DATA/$TARGET_DATE" | cut -f1)
if [ "$COPIED_FILES" -eq "$SRC_FILES" ]; then
printf "\r %-36s ✓ %dm%02ds (%s files, %s)\n" \
"rsync $TARGET_DATE/ → NAS" \
"$(( RSYNC_DUR / 60 ))" "$(( RSYNC_DUR % 60 ))" \
"$COPIED_FILES" "$COPIED_SIZE" | tee -a "$LOG_FILE"
else
printf "\r %-36s ✗ %s / %s files\n" \
"rsync $TARGET_DATE/ → NAS" "$COPIED_FILES" "$SRC_FILES" | tee -a "$LOG_FILE"
fi
else
printf " %-36s %s\n" "rsync $TARGET_DATE/ → NAS" "skipped (no source dir)"
fi
# ─── SUMMARY ──────────────────────────────────────────────────────────────────
TOTAL_ELAPSED=$(( $(date +%s) - SCRIPT_START ))
DB_SIZE=$(du -sh "$NAS_DB" | cut -f1)
echo ""
log "Archive DB size: $DB_SIZE"
log "Total time: $(( TOTAL_ELAPSED / 60 ))m$(( TOTAL_ELAPSED % 60 ))s"
log "Sync complete for $TARGET_DATE"
log "========================================"
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ pkill -f screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ rm -rf ~/.screenpipe/
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ ll
total 0
drwxr-xr-x 2 lukas staff 64 6 May 20:22 .
drwx------+ 92 lukas staff 2944 6 May 20:22 ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.screenpipe $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd .npm
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ ll
total 24
drwx------ 9 lukas staff 288 28 Apr 09:18 .
drwx------+ 92 lukas staff 2944 6 May 20:22 ..
drwx------ 5 lukas staff 160 1 Nov 2021 _cacache
drwx------@ 2 lukas staff 64 28 Apr 09:18 _locks
drwx------ 15 lukas staff 480 27 Apr 19:54 _logs
drwxr-xr-x 67 lukas staff 2144 28 Apr 09:17 _npx
-rw-r--r--@ 1 lukas staff 0 26 Apr 19:10 _update-notifier-last-checked
-rw-r--r-- 1 lukas staff 173 28 Apr 09:18 anonymous-cli-metrics.json
-rw-r--r-- 1 lukas staff 4764 31 Jan 2024 eresolve-report.txt
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ rm -rf ~/.npm/_npx
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/.npm $ cd ..
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ ll
total 52920
drwx------+ 92 lukas staff 2944 6 May 20:22 .
drwxr-xr-x 5 root admin 160 23 Aug 2024 ..
-r-------- 1 lukas staff 7 18 Nov 2021 .CFUserTextEncoding
-rw-r--r--@ 1 lukas staff 28676 27 Apr 09:11 .DS_Store
drwx------+ 10 lukas staff 320 28 Apr 17:07 .Trash
drwx------ 5 lukas staff 160 1 Nov 2021 .aws
-rw-r--r-- 1 lukas staff 341470 29 Sep 2022 .babel.json
-rw-------@ 1 lukas staff 388 25 Jul 2025 .bash_history
-rw-r--r--@ 1 lukas staff 115 18 Apr 13:19 .bashrc
drwxr-xr-x 5 lukas staff 160 11 Mar 2023 .bito
drwx------@ 6 lukas staff 192 9 Apr 19:53 .cache
drwxr-xr-x 20 lukas staff 640 27 Apr 08:58 .claude
-rw------- 1 lukas staff 28647 27 Apr 09:12 .claude.json
drwxr-xr-x@ 20 lukas staff 640 12 Mar 09:12 .codeium
drwxrwxrwx@ 3 lukas staff 96 2 Mar 2023 .composer
drwx------ 16 lukas staff 512 21 May 2025 .config
drwxr-xr-x 15 lukas staff 480 23 Dec 2024 .continue
drwx------@ 3 lukas staff 96 16 Feb 19:13 .copilot
drwxr-xr-x@ 5 lukas staff 160 9 Apr 2025 .cursor
drwxr-xr-x@ 5 lukas staff 160 17 Aug 2024 .cursor-tutor
drwxr-xr-x 3 lukas staff 96 8 Sep 2024 .daytona
drwxr-xr-x@ 4 lukas staff 128 18 Feb 10:52 .devdb
drwx------ 24 lukas staff 768 27 Apr 18:14 .docker
drwx------ 15 lukas staff 480 6 Jun 2023 .dropbox
drwxr-xr-x@ 3 lukas staff 96 20 Nov 2022 .fig.dotfiles.bak
-rw-r--r-- 1 lukas staff 138 5 Mar 2022 .gauth
-rw-r--r-- 1 lukas staff 220 25 Nov 2021 .gitconfig
-rw-r--r-- 1 lukas staff 12288 25 Nov 2021 .gitconfig.swp
drwx------ 5 lukas staff 160 18 Nov 2021 .hammerspoon
drwxr-xr-x 3 lukas staff 96 21 Mar 2025 .idlerc
-rw------- 1 lukas staff 20 28 Apr 16:51 .lesshst
drwx------ 5 lukas staff 160 23 Dec 2024 .local
-rw------- 1 lukas staff 204 16 Mar 2024 .netrc
drwx------ 3 lukas staff 96 1 Nov 2021 .node-gyp
-rw------- 1 lukas staff 4 6 Feb 2024 .node_repl_history
-rw-r--r-- 1 lukas staff 17 24 Dec 2023 .notion-enhancer
drwxr-xr-x 4 lukas staff 128 12 Jul 2024 .notion-py
drwx------ 8 lukas staff 256 6 May 20:24 .npm
-rw------- 1 lukas staff 74 20 May 2024 .npmrc
drwx------ 32 lukas staff 1024 25 Jul 2025 .nvm
drwxr-xr-x 4 lukas staff 128 5 Aug 2023 .postman
-rw-r--r--@ 1 lukas staff 77 9 Feb 2023 .profile
-rw-------@ 1 lukas staff 3153 21 Mar 2025 .python_history
drwx------ 2 lukas staff 64 15 Nov 2021 .quicktype-vscode
drwxr-xr-x@ 8 lukas staff 256 16 Feb 08:48 .redis-insight
drwxr-xr-x 4 lukas staff 128 4 Feb 09:35 .sonarlint
drwx------ 15 lukas staff 480 8 Aug 2025 .ssh
drwxr-xr-x@ 3 lukas staff 96 15 Aug 2025 .streamlit
drwx------ 6 lukas staff 192 17 Oct 2022 .swiftpm
-rw------- 1 lukas staff 12143 27 Apr 14:58 .viminfo
drwx------ 5 lukas staff 160 19 Jun 2023 .vscode
drwxr-xr-x@ 3 lukas staff 96 20 Jan 2025 .warp
UW PICO 5.09 New Buffer
[ Read 1 line ]
^G Get Help ^O WriteOut ^R Read File ^Y Prev Pg ^K Cut Text ^C Cur Pos
^X Exit ^J Justify ^W Where is ^V Next Pg ^U UnCut Text ^T To Spell
drwxr-xr-x 4 lukas staff 128 29 Apr 2023 .wdm
drwxr-xr-x@ 5 lukas staff 160 26 Jan 13:03 .windsurf
drwxr-xr-x 4 lukas staff 128 24 Mar 12:03 .yarn
-rw-r--r-- 1 lukas staff 116 30 Mar 10:12 .yarnrc
-rw-r--r-- 1 lukas staff 49518 21 Apr 09:09 .zcompdump
-rw-r--r--@ 1 lukas staff 46758 2 Nov 2025 .zcompdump.Lukas-Kovaliks-MacBook-Pro-Jiminny.23381
-rw-r--r--@ 1 lukas staff 6116 20 Apr 19:52 .zprofile
-rw-r--r-- 1 lukas staff 1468 8 Apr 2022 .zprofile-copy
-rw-r--r--@ 1 lukas staff 2900 15 Mar 2023 .zprofile.pysave
-rw------- 1 lukas staff 1731 29 Jun 2022 .zprofile.save
-rw-r--r-- 1 lukas staff 1569 8 Apr 2022 .zprofilees
-rw------- 1 lukas staff 50310 28 Apr 11:32 .zsh_history
drwx------ 9 lukas staff 288 6 May 2025 .zsh_sessions
-rw-r--r--@ 1 lukas staff 400 18 Apr 13:19 .zshrc
drwx------@ 9 lukas staff 288 20 Apr 20:55 Applications
drwxr-xr-x@ 2 lukas staff 64 22 Oct 2025 CascadeProjects
drwxr-xr-x 4 lukas staff 128 27 Oct 2025 DEV
drwx------@ 10 lukas staff 320 28 Apr 18:52 Desktop
drwx------@ 7 lukas staff 224 26 Mar 14:40 Documents
drwx------@ 44 lukas staff 1408 24 Apr 16:53 Downloads
drwxr-xr-x@ 4 lukas staff 128 17 Mar 20:27 Keychron_Screen
drwx------@ 112 lukas staff 3584 2 Dec 09:19 Library
drwx------ 7 lukas staff 224 12 Feb 2024 Movies
drwx------+ 5 lukas staff 160 25 Sep 2023 Music
drwx------+ 9 lukas staff 288 25 Sep 2023 Pictures
drwx------ 3 lukas staff 96 8 Nov 2021 Postman
drwx------+ 4 lukas staff 128 28 Oct 2021 Public
-rw-r--r--@ 1 lukas staff 3950 15 Dec 09:16 Untitled 4.spf
drwx------ 4 lukas staff 128 2 Jul 2023 Users
-rw-r--r-- 1 lukas staff 17050804 27 Apr 19:18 cleanshot-live.log
-rw-r--r-- 1 lukas staff 9363061 27 Apr 19:24 cleanshot-screenpipe.log
-rw-r--r-- 1 lukas staff 0 12 Apr 12:50 clip.mp4
-rw-r--r-- 1 lukas staff 0 12 Apr 12:51 frame.jpg
drwx------ 3 lukas staff 96 30 Sep 2022 iCloud Drive (Archive)
drwx------ 16 lukas staff 512 3 Nov 2025 jiminny
drwxr-xr-x 3 lukas staff 96 20 Mar 18:47 node_modules
drwxr-xr-x 4 lukas staff 128 21 Oct 2025 raycast
-rw-r--r-- 1 lukas staff 0 1 Mar 14:26 response.bin
-rwxr-xr-x 1 lukas staff 3824 11 Apr 15:16 screenpipe-day.sh
-rw-r--r-- 1 lukas staff 86 20 Mar 18:47 yarn.lock
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ cd ~/.screenpipe
cd: no such file or directory: /Users/lukas/.screenpipe
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ touch screenpipe_sync.sh
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ nano screenpipe_sync.sh
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ npx screenpipe@latest record --ignored-windows "Boosteroid" --retention-days 7
detected hardware tier: Mid
warning: parakeet is not supported on this platform, using whisper-tiny instead
2026-05-06T20:27:32.721416Z INFO screenpipe_engine::auth_key: api auth: key resolved via auto-generated
checking permissions...
screen recording: ok
microphone: ok
accessibility: ok
2026-05-06T20:27:32.831033Z INFO screenpipe_screen::monitor::macos_version: Detected macOS version: 14.6
2026-05-06T20:27:34.088403Z INFO screenpipe_engine::sleep_monitor: Starting macOS sleep/wake monitor
2026-05-06T20:27:34.089942Z INFO screenpipe_engine::sleep_monitor: Screen lock/unlock observers registered (CFNotificationCenter)
2026-05-06T20:27:34.090417Z INFO screenpipe_engine::sleep_monitor: Display reconfiguration watcher registered (CGDisplayRegisterReconfigurationCallback)
2026-05-06T20:27:34.112650Z INFO screenpipe_engine::permission_monitor: permission monitor started screen=true mic=true accessibility=true keychain=true
2026-05-06T20:27:34.112711Z INFO screenpipe: meeting detector enabled — independent of transcription mode
2026-05-06T20:27:34.619906Z INFO screenpipe: API server listening on [IP_ADDRESS]:3030 (localhost only)
2026-05-06T20:27:34.619937Z INFO screenpipe: API auth enabled — run `screenpipe auth token` to view your key
2026-05-06T20:27:34.619857Z INFO screenpipe_engine::snapshot_compaction: snapshot compaction worker started (min_age=600s, poll=300s)
2026-05-06T20:27:34.619847Z INFO screenpipe_engine::power::manager: power manager started (poll interval: 10s)
2026-05-06T20:27:34.620018Z INFO screenpipe_engine::vision_manager::manager: Starting VisionManager
2026-05-06T20:27:34.624746Z INFO screenpipe_core::pipes: installed built-in pipe: day-recap
2026-05-06T20:27:34.626304Z INFO screenpipe_core::pipes: installed built-in pipe: standup-update
2026-05-06T20:27:34.628597Z INFO screenpipe_core::pipes: installed built-in pipe: ai-habits
2026-05-06T20:27:34.629463Z INFO screenpipe_core::pipes: installed built-in pipe: time-breakdown
2026-05-06T20:27:34.630081Z INFO screenpipe_core::pipes: installed built-in pipe: video-export
2026-05-06T20:27:34.630972Z INFO screenpipe_core::pipes: installed built-in pipe: meeting-summary
2026-05-06T20:27:34.631427Z INFO screenpipe_core::pipes: loaded pipe: day-recap
2026-05-06T20:27:34.631521Z INFO screenpipe_core::pipes: loaded pipe: standup-update
2026-05-06T20:27:34.631587Z INFO screenpipe_core::pipes: loaded pipe: ai-habits
2026-05-06T20:27:34.631640Z INFO screenpipe_core::pipes: loaded pipe: time-breakdown
2026-05-06T20:27:34.631690Z INFO screenpipe_core::pipes: loaded pipe: video-export
2026-05-06T20:27:34.631738Z INFO screenpipe_core::pipes: loaded pipe: meeting-summary
2026-05-06T20:27:34.631752Z INFO screenpipe_core::pipes: loaded 6 pipes from "/Users/lukas/.screenpipe/pipes"
_
__________________ ___ ____ ____ (_____ ___
/ ___/ ___/ ___/ _ \/ _ \/ __ \ / __ \/ / __ \/ _ \
(__ / /__/ / / __/ __/ / / / / /_/ / / /_/ / __/
/____/\___/_/ \___/\___/_/ /_/ / .___/_/ .___/\___/
/_/ /_/
power AI by everything you've seen, said or heard
open source | runs locally | developer friendly
┌────────────────────────┬────────────────────────────────────┐
│ setting │ value │
├────────────────────────┼────────────────────────────────────┤
│ audio chunk duration │ 30 seconds │
│ port │ 3030 │
│ audio disabled │ false │
│ vision disabled │ false │
│ pause on DRM content │ false │
│ audio engine │ Parakeet │
│ vad engine │ Silero │
│ data directory │ /Users/lukas/.screenpipe │
│ debug mode │ false │
│ telemetry │ true │
│ use pii removal │ true │
│ use all monitors │ true │
│ ignored windows │ ["Boosteroid"] │
│ included windows │ [] │
│ cloud sync │ disabled │
│ auto-destruct pid │ 0 │
│ deepgram key │ not set │
│ api auth │ enabled │
│ encrypt secrets │ disabled │
│ retention days │ 7 │
│ retention mode │ media-only (keep transcripts) │
├────────────────────────┼────────────────────────────────────┤
│ languages │ │
│ │ all languages │
├────────────────────────┼────────────────────────────────────┤
│ monitors │ │
│ │ id: 1 │
│ │ id: 2 │
├────────────────────────┼────────────────────────────────────┤
│ audio devices │ │
│ │ MacBook Pro Microphone (input) │
│ │ System Audio (output) │
└────────────────────────┴────────────────────────────────────┘
you are using local processing. all your data stays on your computer.
warning: telemetry is enabled. only error-level data will be sent.
to disable, use the --disable-telemetry flag.
check latest changes here: [URL_WITH_CREDENTIALS] ~ $ 2026-05-06T20:31:45.865813Z INFO screenpipe_audio::device::device_manager: Stopping device: MacBook Pro Microphone (input)
2026-05-06T20:31:45.865820Z INFO screenpipe_audio::device::device_manager: Stopping device: MacBook Pro Microphone (input)
2026-05-06T20:31:45.892593Z INFO screenpipe_audio::audio_manager::manager: audio manager stopped
2026-05-06T20:31:45.892684Z INFO screenpipe: stopping UI event capture
2026-05-06T20:31:45.893002Z INFO screenpipe_engine::meeting_detector: meeting v2: shutdown received, exiting detection loop
2026-05-06T20:31:45.893977Z INFO screenpipe: received shutdown signal for VisionManager
2026-05-06T20:31:45.894556Z INFO screenpipe_engine::vision_manager::manager: Shutting down VisionManager
2026-05-06T20:31:45.894516Z INFO screenpipe_engine::snapshot_compaction: snapshot compaction worker shutting down
2026-05-06T20:31:45.894602Z INFO screenpipe_engine::vision_manager::manager: Stopping VisionManager
2026-05-06T20:31:45.895419Z INFO screenpipe_engine::vision_manager::manager: Stopping vision recording for monitor 2
2026-05-06T20:31:45.895898Z INFO screenpipe_engine::vision_manager::manager: Stopping vision recording for monitor 1
2026-05-06T20:31:45.980559Z INFO screenpipe_engine::ui_recorder: UI recording session ended: 54869993-7b4b-491f-b717-2a583517f9c5
2026-05-06T20:31:45.980777Z INFO screenpipe: shutdown complete
ggml_metal_free: deallocating
2026-05-06T20:31:46.374234Z ERROR screenpipe_engine::event_driven_capture: event capture failed (trigger=click, monitor=1): monitor capture failed: capture task panicked: task 770 was cancelled
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ ;3B
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ sp-start
detected hardware tier: Mid
warning: parakeet is not supported on this platform, using whisper-tiny instead
2026-05-06T20:32:21.850318Z INFO screenpipe_engine::auth_key: api auth: key resolved via secret store
checking permissions...
screen recording: ok
accessibility: ok
2026-05-06T20:32:21.937393Z INFO screenpipe_screen::monitor::macos_version: Detected macOS version: 14.6
2026-05-06T20:32:23.002257Z INFO screenpipe_engine::sleep_monitor: Starting macOS sleep/wake monitor
2026-05-06T20:32:23.006683Z INFO screenpipe_engine::sleep_monitor: Screen lock/unlock observers registered (CFNotificationCenter)
2026-05-06T20:32:23.008348Z INFO screenpipe_engine::sleep_monitor: Display reconfiguration watcher registered (CGDisplayRegisterReconfigurationCallback)
2026-05-06T20:32:23.030912Z INFO screenpipe_engine::permission_monitor: permission monitor started screen=true mic=true accessibility=true keychain=true
2026-05-06T20:32:23.030979Z INFO screenpipe: meeting detector enabled — independent of transcription mode
2026-05-06T20:32:23.031261Z INFO screenpipe: API server listening on [IP_ADDRESS]:3030 (localhost only)
2026-05-06T20:32:23.031328Z INFO screenpipe_engine::vision_manager::manager: Starting VisionManager
2026-05-06T20:32:23.031199Z INFO screenpipe_engine::snapshot_compaction: snapshot compaction worker started (min_age=600s, poll=300s)
2026-05-06T20:32:23.031387Z INFO screenpipe: API auth enabled — run `screenpipe auth token` to view your key
2026-05-06T20:32:23.031253Z INFO screenpipe_engine::power::manager: power manager started (poll interval: 10s)
2026-05-06T20:32:23.034682Z INFO screenpipe_core::pipes: loaded pipe: day-recap
2026-05-06T20:32:23.035042Z INFO screenpipe_core::pipes: loaded pipe: standup-update
2026-05-06T20:32:23.035480Z INFO screenpipe_core::pipes: loaded pipe: ai-habits
2026-05-06T20:32:23.035607Z INFO screenpipe_core::pipes: loaded pipe: time-breakdown
2026-05-06T20:32:23.035705Z INFO screenpipe_core::pipes: load...
|
iTerm2
|
screenpipe"
|
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_...
|
iTerm2
|
screenpipe"
|
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...
|
iTerm2
|
-zsh
|
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...
|
iTerm2
|
-zsh
|
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...
|
iTerm2
|
-zsh
|
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...
|
iTerm2
|
-zsh
|
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...
|
iTerm2
|
-zsh
|
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...
|
iTerm2
|
-zsh
|
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...
|
iTerm2
|
-zsh
|
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...
|
iTerm2
|
-zsh
|
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...
|
iTerm2
|
-zsh
|
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...
|
iTerm2
|
-zsh
|
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...
|
iTerm2
|
-zsh
|
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...
|
iTerm2
|
-zsh
|
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...
|
iTerm2
|
-zsh
|
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...
|
iTerm2
|
-zsh
|
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...
|
iTerm2
|
-zsh
|
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...
|
iTerm2
|
-zsh
|
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...
|
iTerm2
|
-zsh
|
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...
|
iTerm2
|
-zsh
|
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...
|
iTerm2
|
-zsh
|
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...
|
iTerm2
|
-zsh
|
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...
|
iTerm2
|
-zsh
|
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...
|
iTerm2
|
-zsh
|
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...
|
iTerm2
|
-zsh
|
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...
|
iTerm2
|
-zsh
|
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...
|
iTerm2
|
-zsh
|
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...
|
iTerm2
|
-zsh
|
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...
|
iTerm2
|
-zsh
|
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...
|
iTerm2
|
-zsh
|
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...
|
iTerm2
|
-zsh
|
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...
|
iTerm2
|
-zsh
|
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...
|
iTerm2
|
-zsh
|
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...
|
iTerm2
|
-zsh
|
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...
|
iTerm2
|
-zsh
|
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...
|
iTerm2
|
-zsh
|
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...
|
iTerm2
|
-zsh
|
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...
|
iTerm2
|
-zsh
|
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...
|
iTerm2
|
-zsh
|
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...
|
QuickTime Player
|
compact_monitor_1_1778089220643.mp4
|
NULL
|
|
rewind
play/pause
fast forward
More Controls
toggl rewind
play/pause
fast forward
More Controls
toggle full screen
show external playback menu
show external playback menu
show media selection menu
toggle picture-in-picture playback
show action menu
share
show chapter menu
zoom
zoom
playback speed
00:02
toggle elapsed time, timecode and framecount
02:10
toggle duration and remaining time
document actions
compact_monitor_1_1778089220643.mp4
DMSAC.MILVAll 4DMsloastApp[no preview availablel11 | 10:00 AMIMonday. May 4th-7 Jira Cloud@ 15 Monday@Nikolay Ivanov transitioned aBug you are watching from Code...Wednesday, April 29thAneliva AngelovaWednesdayStoyan Tanev6 DMWednesdavнаша стоананTuesday. April 28th?1 Stefka StoyanovaApr 28thтия тикети е добре да влезнат вдругия спринт ли? сложете някакви...Ves@ Thread in DM: исках да те...смени го в Circle Cl env на новиятокен който си напларилApr 28thStefka Stoyano… Replied Apr 28thAOMIпnuaтна oтлуска СStetka Stovanova and …... Aor 28thl•• 0‹→ сN& Adelina Petrova "Pull requests • screenpipe/screenpipe • GitHubMessagesLo Add canvasUr Files# Hostinger login | Sign in to Hostinger accountне, само стр се тракватLogin - Nginx Proxy ManagerLukas Kovalik IN 1:15 PM* Screenpipe - ArchiveAdelina Petrova "T 1:42 PMpagesLukas Kovalik "T 1:43 PMЯСНО@ SQLite Web: archive.db©SQLite Web: db.sqliteAdelina Petrova 5:06 PMда не ои проолема да е заради това кю: QUEUE,DELAYANew TabLukas Kovalik * 5:06 PMscreenpipe/,claude/skills at main • screenpipe/screenpза това искам да дооавя логовеAdelina Petrova 5:07 PMUAVDA MO CTAUG SUA rA MaVUOLI?има ли риск за нещоLukas Kovalik " 5:08 PMвсишност нама опашка тукаAdelina Petrova " 5:12 PM• сега, няма ли ла сложи евента в това кю и ла цака изпьл.Lukas Kovalik *T 5:21 PMла, ше оставя detault изпь лнениеLukas Kovalik 1K 5-26 PMпо поинцип го направих като nudge-created че те не са о!•и глелам че и този event няма никойAdelina Petrova" 5:33PMспорел мен пробвай без това кюLukas Kovalik * 5:33 PMhttps://run.userpilot.io/events/tracked_event/10run.userpilot.ioUserpilotUserpilot helos product teams deliver personalized in-appgrowth metrics at every stage of the user lournev.не е това обаче, гледам че всички си минават през сьщиAdelina Petrova * 5:40 PMами эко можеш сложи тогава лог да го видимAdelina Petrova has paused their notificationsMessage Adelina Petrova " VacationingAaO Not Secure http:/[IP_ADDRESS]:8768/audio_transcriptions_fts_idx/audio_tagsaualo transcriptionsaudio_transcriptions_fts (v)audio_transcriptions_audio_transcriptions_.audio_transcriptions_...elementselements_fts (v)elements_fts_configelements_fts_dataelements_fts_idxframesframes_fts (")frames_fts_configframes_fts_dataframes_fts_idxmeetingsmemoriesmemories_fts (v)memories_fts_configmemories_fts_datamemories_fts_idxocr_textpipe_executionspipe_scheduler_statesecretsspeaker_embeddingsspeakerssqlite_sequencesqlite_statlsalite_statatagsui_eventsui_events_fts (v)ui_events_fts_configui_events_fts_dataui_events_fts_idxvideo_chunksvision_tagsCREATE TABLE 'audio_transcriptions_fts_idx' (segid,term,PRIMARY KEY(segid, term)ColumnsColumnData typesegidpgnoIndexesNameColumnsSQLite database browser v0.7.2, powered by Flask and Peewee. © 2026 Charles LeiferToggle helper tablesAllow nullUniquePrimary keySOLW6MaY 20:43:27OSOEOEActionsread-onlyread-onlyread-onlyDrop?...
|
QuickTime Player
|
compact_monitor_1_1778089220643.mp4
|
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...
|
QuickTime Player
|
compact_monitor_1_1778089220643.mp4
|
NULL
|
|
rewind
play/pause
fast forward
More Controls
toggl rewind
play/pause
fast forward
More Controls
toggle full screen
show external playback menu
show external playback menu
show media selection menu
toggle picture-in-picture playback
show action menu
share
show chapter menu
zoom
zoom
playback speed
00:00
toggle elapsed time, timecode and framecount
02:10
toggle duration and remaining time
document actions
compact_monitor_1_1778089220643.mp4
DMSAC.MILVAll 4DMsloastApp[no preview availablel11 | 10:00 AMIMonday. May 4th-7 Jira Cloud@ 15 Monday@Nikolay Ivanov transitioned aBug you are watching from Code...Wednesday, April 29thAneliva AngelovaWednesdayStoyan Tanev6 DMWednesdavнаша стоананTuesday. April 28th?1 Stefka StoyanovaApr 28thтия тикети е добре да влезнат вдругия спринт ли? сложете някакви...Ves@ Thread in DM: исках да те...смени го в Circle Cl env на новиятокен който си напларилApr 28thStefka Stoyano… Replied Apr 28thAOMIпnuaтна oтлуска СStetka Stovanova and …... Aor 28thl•• 0‹→ сN& Adelina Petrova "Pull requests • screenpipe/screenpipe • GitHubMessagesLo Add canvasUr Files# Hostinger login | Sign in to Hostinger accountне, само стр се тракватLogin - Nginx Proxy ManagerLukas Kovalik IN 1:15 PM* Screenpipe - ArchiveAdelina Petrova "T 1:42 PMpagesLukas Kovalik "T 1:43 PMЯСНО@ SQLite Web: archive.db©SQLite Web: db.sqliteAdelina Petrova 5:06 PMда не ои проолема да е заради това кю: QUEUE,DELAYANew TabLukas Kovalik * 5:06 PMscreenpipe/,claude/skills at main • screenpipe/screenpза това искам да дооавя логовеAdelina Petrova 5:07 PMUAVDA MO CTAUG SUA rA MaVUOLI?има ли риск за нещоLukas Kovalik " 5:08 PMвсишност нама опашка тукаAdelina Petrova " 5:12 PM• сега, няма ли ла сложи евента в това кю и ла цака изпьл.Lukas Kovalik *T 5:21 PMла, ше оставя detault изпь лнениеLukas Kovalik 1K 5-26 PMпо поинцип го направих като nudge-created че те не са о!•и глелам че и този event няма никойAdelina Petrova" 5:33PMспорел мен пробвай без това кюLukas Kovalik * 5:33 PMhttps://run.userpilot.io/events/tracked_event/10run.userpilot.ioUserpilotUserpilot helos product teams deliver personalized in-appgrowth metrics at every stage of the user lournev.не е това обаче, гледам че всички си минават през сьщиAdelina Petrova * 5:40 PMами эко можеш сложи тогава лог да го видимAdelina Petrova has paused their notificationsMessage Adelina Petrova " VacationingAaO Not Secure http:/[IP_ADDRESS]:8768/audio_transcriptions_fts_idx/audio_tagsaualo transcriptionsaudio_transcriptions_fts (v)audio_transcriptions_audio_transcriptions_.audio_transcriptions_...elementselements_fts (v)elements_fts_configelements_fts_dataelements_fts_idxframesframes_fts (")frames_fts_configframes_fts_dataframes_fts_idxmeetingsmemoriesmemories_fts (v)memories_fts_configmemories_fts_datamemories_fts_idxocr_textpipe_executionspipe_scheduler_statesecretsspeaker_embeddingsspeakerssqlite_sequencesqlite_statlsalite_statatagsui_eventsui_events_fts (v)ui_events_fts_configui_events_fts_dataui_events_fts_idxvideo_chunksvision_tagsCREATE TABLE 'audio_transcriptions_fts_idx' (segid,term,PRIMARY KEY(segid, term)ColumnsColumnData typesegidpgnoIndexesNameColumnsSQLite database browser v0.7.2, powered by Flask and Peewee. © 2026 Charles LeiferToggle helper tablesAllow nullUniquePrimary keySOLW6MaY 20:43:30Actionsread-onlyread-onlyread-onlyDrop?...
|
QuickTime Player
|
compact_monitor_1_1778089220643.mp4
|
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...
|
QuickTime Player
|
compact_monitor_1_1778089220643.mp4
|
NULL
|
|
rewind
play/pause
fast forward
More Controls
toggl rewind
play/pause
fast forward
More Controls
toggle full screen
show external playback menu
show external playback menu
show media selection menu
toggle picture-in-picture playback
show action menu
share
show chapter menu
zoom
zoom
playback speed
00:03
toggle elapsed time, timecode and framecount
02:10
toggle duration and remaining time
document actions
compact_monitor_1_1778089220643.mp4
DMSAC.MILVAll 4DMsloastApp[no preview availablel11 | 10:00 AMIMonday. May 4th-7 Jira Cloud@ 15 Monday@Nikolay Ivanov transitioned aBug you are watching from Code...Wednesday, April 29thAneliva AngelovaWednesdayStoyan Tanev6 DMWednesdavнаша стоананTuesday. April 28th?1 Stefka StoyanovaApr 28thтия тикети е добре да влезнат вдругия спринт ли? сложете някакви...Ves@ Thread in DM: исках да те...смени го в Circle Cl env на новиятокен който си напларилApr 28thStefka Stoyano… Replied Apr 28thAOMIпnuaтна oтлуска СStetka Stovanova and …... Aor 28thl•• 0‹→ сN& Adelina Petrova "Pull requests • screenpipe/screenpipe • GitHubMessagesLo Add canvasUr Files# Hostinger login | Sign in to Hostinger accountне, само стр се тракватLogin - Nginx Proxy ManagerLukas Kovalik IN 1:15 PM* Screenpipe - ArchiveAdelina Petrova "T 1:42 PMpagesLukas Kovalik "T 1:43 PMЯСНО@ SQLite Web: archive.db©SQLite Web: db.sqliteAdelina Petrova 5:06 PMда не ои проолема да е заради това кю: QUEUE,DELAYANew TabLukas Kovalik * 5:06 PMscreenpipe/,claude/skills at main • screenpipe/screenpза това искам да дооавя логовеAdelina Petrova 5:07 PMUAVDA MO CTAUG SUA rA MaVUOLI?има ли риск за нещоLukas Kovalik " 5:08 PMвсишност нама опашка тукаAdelina Petrova " 5:12 PM• сега, няма ли ла сложи евента в това кю и ла цака изпьл.Lukas Kovalik *T 5:21 PMла, ше оставя detault изпь лнениеLukas Kovalik 1K 5-26 PMпо поинцип го направих като nudge-created че те не са о!•и глелам че и този event няма никойAdelina Petrova" 5:33PMспорел мен пробвай без това кюLukas Kovalik * 5:33 PMhttps://run.userpilot.io/events/tracked_event/10run.userpilot.ioUserpilotUserpilot helos product teams deliver personalized in-appgrowth metrics at every stage of the user lournev.не е това обаче, гледам че всички си минават през сьщиAdelina Petrova * 5:40 PMами эко можеш сложи тогава лог да го видимAdelina Petrova has paused their notificationsMessage Adelina Petrova " VacationingAaO Not Secure http:/[IP_ADDRESS]:8768/audio_transcriptions_fts_idx/audio_tagsaualo transcriptionsaudio_transcriptions_fts (v)audio_transcriptions_audio_transcriptions_.audio_transcriptions_...elementselements_fts (v)elements_fts_configelements_fts_dataelements_fts_idxframesframes_fts (")frames_fts_configframes_fts_dataframes_fts_idxmeetingsmemoriesmemories_fts (v)memories_fts_configmemories_fts_datamemories_fts_idxocr_textpipe_executionspipe_scheduler_statesecretsspeaker_embeddingsspeakerssqlite_sequencesqlite_statlsalite_statatagsui_eventsui_events_fts (v)ui_events_fts_configui_events_fts_dataui_events_fts_idxvideo_chunksvision_tagsCREATE TABLE 'audio_transcriptions_fts_idx' (segid,term,PRIMARY KEY(segid, term)ColumnsColumnData typesegidpgnoIndexesNameColumnsSQLite database browser v0.7.2, powered by Flask and Peewee. © 2026 Charles LeiferToggle helper tablesAllow nullUniquePrimary keySOL432OSOEOEActionsread-onlyread-onlyread-onlyDrop?...
|
QuickTime Player
|
compact_monitor_1_1778089220643.mp4
|
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...
|
QuickTime Player
|
compact_monitor_1_1778089220643.mp4
|
NULL
|
|
rewind
play/pause
fast forward
More Controls
toggl rewind
play/pause
fast forward
More Controls
toggle full screen
show external playback menu
show external playback menu
show media selection menu
toggle picture-in-picture playback
show action menu
share
show chapter menu
zoom
zoom
playback speed
00:21
toggle elapsed time, timecode and framecount
02:10
toggle duration and remaining time
document actions
compact_monitor_1_1778089220643.mp4
DMSAC.MILVAll 4DMsloastApp[no preview availablel11 | 10:00 AMIMonday. May 4th-7 Jira Cloud@ 15 Monday@Nikolay Ivanov transitioned aBug you are watching from Code...Wednesday, April 29thAneliva AngelovaWednesdayStoyan Tanev6 DMWednesdavнаша стоананTuesday. April 28th?1 Stefka StoyanovaApr 28thтия тикети е добре да влезнат вдругия спринт ли? сложете някакви...Ves@ Thread in DM: исках да те...смени го в Circle Cl env на новиятокен който си напларилApr 28thStefka Stoyano… Replied Apr 28thAOMIпnuaтна oтлуска СStetka Stovanova and …... Aor 28thl•• 0‹→ сN& Adelina Petrova "Pull requests • screenpipe/screenpipe • GitHubMessagesLo Add canvasUr Files# Hostinger login | Sign in to Hostinger accountне, само стр се тракватLogin - Nginx Proxy ManagerLukas Kovalik IN 1:15 PM* Screenpipe - ArchiveAdelina Petrova "T 1:42 PMpagesLukas Kovalik "T 1:43 PMЯСНО@ SQLite Web: archive.db©SQLite Web: db.sqliteAdelina Petrova 5:06 PMда не ои проолема да е заради това кю: QUEUE,DELAYANew TabLukas Kovalik * 5:06 PMscreenpipe/,claude/skills at main • screenpipe/screenpза това искам да дооавя логовеAdelina Petrova 5:07 PMUAVDA MO CTAUG SUA rA MaVUOLI?има ли риск за нещоLukas Kovalik " 5:08 PMвсишност нама опашка тукаAdelina Petrova " 5:12 PM• сега, няма ли ла сложи евента в това кю и ла цака изпьл.Lukas Kovalik *T 5:21 PMла, ше оставя detault изпь лнениеLukas Kovalik 1K 5-26 PMпо поинцип го направих като nudge-created че те не са о!•и глелам че и този event няма никойAdelina Petrova" 5:33PMспорел мен пробвай без това кюLukas Kovalik * 5:33 PMhttps://run.userpilot.io/events/tracked_event/10run.userpilot.ioUserpilotUserpilot helos product teams deliver personalized in-appgrowth metrics at every stage of the user lournev.не е това обаче, гледам че всички си минават през сьщиAdelina Petrova * 5:40 PMами эко можеш сложи тогава лог да го видимAdelina Petrova has paused their notificationsMessage Adelina Petrova " VacationingAaO Not Secure http:/[IP_ADDRESS]:8768/audio_transcriptions_fts_idx/audio_tagsaualo transcriptionsaudio_transcriptions_fts (v)audio_transcriptions_audio_transcriptions_.audio_transcriptions_...elementselements_fts (v)elements_fts_configelements_fts_dataelements_fts_idxframesframes_fts (")frames_fts_configframes_fts_dataframes_fts_idxmeetingsmemoriesmemories_fts (v)memories_fts_configmemories_fts_datamemories_fts_idxocr_textpipe_executionspipe_scheduler_statesecretsspeaker_embeddingsspeakerssqlite_sequencesqlite_statlsalite_statatagsui_eventsui_events_fts (v)ui_events_fts_configui_events_fts_dataui_events_fts_idxvideo_chunksvision_tagsCREATE TABLE 'audio_transcriptions_fts_idx' (segid,term,PRIMARY KEY(segid, term)ColumnsColumnData typesegidpgnoIndexesNameColumnsSQLite database browser v0.7.2, powered by Flask and Peewee. © 2026 Charles LeiferToggle helper tablesAllow nullUniquePrimary keySOLActionsread-onlyread-onlyread-onlyDrop?...
|
QuickTime Player
|
compact_monitor_1_1778089220643.mp4
|
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...
|
QuickTime Player
|
compact_monitor_1_1778089220643.mp4
|
NULL
|