screenpipe-sync 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -7,17 +7,17 @@ Turn hours of screen recordings into actionable context: todos, goals, decisions
7
7
  ## Quick Start
8
8
 
9
9
  ```bash
10
- # One-liner - outputs to stdout
11
- bunx @screenpipe/sync
10
+ # One-liner - AI summary to stdout
11
+ bunx screenpipe-sync
12
12
 
13
- # Save to a folder (creates YYYY-MM-DD.md files)
14
- bunx @screenpipe/sync --output ~/Documents/brain/context
13
+ # Save daily summaries locally
14
+ bunx screenpipe-sync --output ~/Documents/brain/context --git
15
15
 
16
- # Auto commit and push
17
- bunx @screenpipe/sync --output ~/notes --git
16
+ # Sync raw SQLite database to remote (full history!)
17
+ bunx screenpipe-sync --db --remote user@host:~/.screenpipe/
18
18
 
19
- # Sync to remote server (e.g., Clawdbot)
20
- bunx @screenpipe/sync --remote user@host:~/brain/context
19
+ # Full sync: DB + daily summary
20
+ bunx screenpipe-sync --db -r clawdbot:~/.screenpipe && bunx screenpipe-sync -o ~/context -g
21
21
  ```
22
22
 
23
23
  ## What It Extracts
@@ -114,12 +114,23 @@ bunx @screenpipe/sync --hours 168 --json > week.json
114
114
 
115
115
  ## How It Works
116
116
 
117
+ ### Summary Mode (default)
117
118
  1. **Query** - Fetches OCR data from local Screenpipe API
118
119
  2. **Dedupe** - Removes duplicate/similar screen captures
119
120
  3. **Extract** - Claude analyzes content for structured data
120
121
  4. **Format** - Outputs markdown or JSON
121
122
  5. **Sync** - Optionally git pushes or SCPs to remote
122
123
 
124
+ ### DB Sync Mode (`--db`)
125
+ 1. **Copy** - Copies `~/.screenpipe/db.sqlite` (your full history)
126
+ 2. **Sync** - Uses rsync/scp to transfer to remote
127
+ 3. **Query** - Remote can query SQLite directly
128
+
129
+ ```bash
130
+ # On remote, query your full history:
131
+ sqlite3 ~/.screenpipe/db.sqlite "SELECT text FROM ocr_text WHERE text LIKE '%meeting%' LIMIT 10;"
132
+ ```
133
+
123
134
  ## Requirements
124
135
 
125
136
  - [Screenpipe](https://github.com/mediar-ai/screenpipe) running locally
package/dist/index.js CHANGED
@@ -9603,6 +9603,7 @@ var sdk_default = Anthropic;
9603
9603
  // src/index.ts
9604
9604
  function parseArgs() {
9605
9605
  const args = process.argv.slice(2);
9606
+ const home = process.env.HOME || process.env.USERPROFILE || "~";
9606
9607
  const config = {
9607
9608
  screenpipeUrl: process.env.SCREENPIPE_URL || "http://localhost:3030",
9608
9609
  outputDir: null,
@@ -9614,7 +9615,9 @@ function parseArgs() {
9614
9615
  ollamaUrl: process.env.OLLAMA_URL || "http://localhost:11434",
9615
9616
  ollamaModel: process.env.OLLAMA_MODEL || "llama3.2",
9616
9617
  format: "markdown",
9617
- verbose: false
9618
+ verbose: false,
9619
+ dbSync: false,
9620
+ dbPath: process.env.SCREENPIPE_DB || `${home}/.screenpipe/db.sqlite`
9618
9621
  };
9619
9622
  for (let i2 = 0;i2 < args.length; i2++) {
9620
9623
  const arg = args[i2];
@@ -9642,6 +9645,13 @@ function parseArgs() {
9642
9645
  case "-v":
9643
9646
  config.verbose = true;
9644
9647
  break;
9648
+ case "--db":
9649
+ case "--db-sync":
9650
+ config.dbSync = true;
9651
+ break;
9652
+ case "--db-path":
9653
+ config.dbPath = args[++i2];
9654
+ break;
9645
9655
  case "--help":
9646
9656
  printHelp();
9647
9657
  process.exit(0);
@@ -9651,10 +9661,14 @@ function parseArgs() {
9651
9661
  }
9652
9662
  function printHelp() {
9653
9663
  console.log(`
9654
- @screenpipe/sync - Extract daily context from Screenpipe
9664
+ screenpipe-sync - Extract daily context from Screenpipe
9655
9665
 
9656
9666
  USAGE:
9657
- bunx @screenpipe/sync [options]
9667
+ bunx screenpipe-sync [options]
9668
+
9669
+ MODES:
9670
+ Summary mode (default): AI-powered daily summary extraction
9671
+ DB sync mode (--db): Copy raw SQLite database to remote
9658
9672
 
9659
9673
  OPTIONS:
9660
9674
  -o, --output <dir> Save summary to directory (default: stdout)
@@ -9664,18 +9678,28 @@ OPTIONS:
9664
9678
  --json Output as JSON instead of markdown
9665
9679
  -v, --verbose Show debug output
9666
9680
 
9681
+ --db, --db-sync Sync raw SQLite database instead of summary
9682
+ --db-path <path> Path to Screenpipe DB (default: ~/.screenpipe/db.sqlite)
9683
+
9667
9684
  ENVIRONMENT:
9668
9685
  SCREENPIPE_URL Screenpipe API URL (default: http://localhost:3030)
9669
- ANTHROPIC_API_KEY Required for AI summarization
9686
+ SCREENPIPE_DB Path to Screenpipe database
9687
+ ANTHROPIC_API_KEY For AI summarization (or OPENAI_API_KEY)
9670
9688
 
9671
9689
  EXAMPLES:
9672
- bunx @screenpipe/sync
9673
- bunx @screenpipe/sync --output ~/Documents/brain/context --git
9674
- bunx @screenpipe/sync --hours 24 --json
9675
- bunx @screenpipe/sync --remote clawdbot:~/brain/context
9690
+ # AI summary to stdout
9691
+ bunx screenpipe-sync
9692
+
9693
+ # Save daily summaries locally
9694
+ bunx screenpipe-sync --output ~/Documents/brain/context --git
9676
9695
 
9677
- OUTPUT:
9678
- Creates structured daily summaries with:
9696
+ # Sync raw database to remote (e.g., Clawdbot)
9697
+ bunx screenpipe-sync --db --remote user@clawdbot:~/.screenpipe/
9698
+
9699
+ # Full sync: DB + daily summary
9700
+ bunx screenpipe-sync --db -r clawdbot:~/.screenpipe && bunx screenpipe-sync -o ~/context -g
9701
+
9702
+ OUTPUT (summary mode):
9679
9703
  - Todo items extracted from screen content
9680
9704
  - Goals and intentions mentioned
9681
9705
  - Decisions made
@@ -9683,6 +9707,10 @@ OUTPUT:
9683
9707
  - Meetings and conversations
9684
9708
  - Blockers and problems
9685
9709
  - AI-generated insights
9710
+
9711
+ OUTPUT (db mode):
9712
+ - Copies ~/.screenpipe/db.sqlite to remote
9713
+ - Remote can query SQLite directly for full history
9686
9714
  `);
9687
9715
  }
9688
9716
  async function queryScreenpipe(config) {
@@ -9921,9 +9949,74 @@ async function writeOutput(content, config, filename) {
9921
9949
  }
9922
9950
  }
9923
9951
  }
9952
+ async function syncDatabase(config) {
9953
+ const fs2 = await import("fs/promises");
9954
+ const { execSync } = await import("child_process");
9955
+ try {
9956
+ await fs2.access(config.dbPath);
9957
+ } catch {
9958
+ console.error(`[error] Database not found at ${config.dbPath}`);
9959
+ console.error(` Set --db-path or SCREENPIPE_DB environment variable`);
9960
+ process.exit(1);
9961
+ }
9962
+ const stats = await fs2.stat(config.dbPath);
9963
+ const sizeMB = (stats.size / 1024 / 1024).toFixed(1);
9964
+ console.error(`[db] Found database: ${config.dbPath} (${sizeMB} MB)`);
9965
+ if (!config.remote && !config.outputDir) {
9966
+ console.error(`[error] --db requires --remote or --output to specify destination`);
9967
+ process.exit(1);
9968
+ }
9969
+ if (config.outputDir) {
9970
+ const path = await import("path");
9971
+ const destDir = path.resolve(config.outputDir);
9972
+ await fs2.mkdir(destDir, { recursive: true });
9973
+ const destPath = path.join(destDir, "db.sqlite");
9974
+ console.error(`[db] Copying to ${destPath}...`);
9975
+ await fs2.copyFile(config.dbPath, destPath);
9976
+ try {
9977
+ await fs2.copyFile(`${config.dbPath}-wal`, `${destPath}-wal`);
9978
+ await fs2.copyFile(`${config.dbPath}-shm`, `${destPath}-shm`);
9979
+ } catch {}
9980
+ console.error(`[ok] Database copied to ${destPath}`);
9981
+ if (config.gitPush) {
9982
+ try {
9983
+ execSync(`cd "${destDir}" && git add -A && git commit -m "db sync $(date +%Y-%m-%d)" && git push`, {
9984
+ stdio: config.verbose ? "inherit" : "pipe"
9985
+ });
9986
+ console.error(`[ok] Git pushed`);
9987
+ } catch {
9988
+ console.error(`[warn] Git push failed - maybe no changes?`);
9989
+ }
9990
+ }
9991
+ }
9992
+ if (config.remote) {
9993
+ console.error(`[db] Syncing to ${config.remote}...`);
9994
+ try {
9995
+ execSync(`rsync -avz --progress "${config.dbPath}" "${config.remote}/db.sqlite"`, {
9996
+ stdio: config.verbose ? "inherit" : "pipe"
9997
+ });
9998
+ console.error(`[ok] Database synced to ${config.remote}`);
9999
+ } catch {
10000
+ try {
10001
+ execSync(`scp "${config.dbPath}" "${config.remote}/db.sqlite"`, {
10002
+ stdio: config.verbose ? "inherit" : "pipe"
10003
+ });
10004
+ console.error(`[ok] Database copied to ${config.remote}`);
10005
+ } catch (e2) {
10006
+ console.error(`[error] Failed to sync database: ${e2}`);
10007
+ process.exit(1);
10008
+ }
10009
+ }
10010
+ }
10011
+ console.error(`[done] Database sync complete`);
10012
+ }
9924
10013
  async function main() {
9925
10014
  const config = parseArgs();
9926
10015
  const today = new Date().toISOString().split("T")[0];
10016
+ if (config.dbSync) {
10017
+ await syncDatabase(config);
10018
+ return;
10019
+ }
9927
10020
  console.error(`[screenpipe-sync] Analyzing last ${config.hours} hours...`);
9928
10021
  const results = await queryScreenpipe(config);
9929
10022
  console.error(`[ok] Retrieved ${results.length} screen captures`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "screenpipe-sync",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Sync Screenpipe activity to structured daily summaries. Extract todos, goals, decisions from your screen history.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/index.ts CHANGED
@@ -51,6 +51,8 @@ interface Config {
51
51
  ollamaModel: string;
52
52
  format: "markdown" | "json";
53
53
  verbose: boolean;
54
+ dbSync: boolean;
55
+ dbPath: string;
54
56
  }
55
57
 
56
58
  // ============================================================================
@@ -59,6 +61,7 @@ interface Config {
59
61
 
60
62
  function parseArgs(): Config {
61
63
  const args = process.argv.slice(2);
64
+ const home = process.env.HOME || process.env.USERPROFILE || "~";
62
65
  const config: Config = {
63
66
  screenpipeUrl: process.env.SCREENPIPE_URL || "http://localhost:3030",
64
67
  outputDir: null,
@@ -71,6 +74,8 @@ function parseArgs(): Config {
71
74
  ollamaModel: process.env.OLLAMA_MODEL || "llama3.2",
72
75
  format: "markdown",
73
76
  verbose: false,
77
+ dbSync: false,
78
+ dbPath: process.env.SCREENPIPE_DB || `${home}/.screenpipe/db.sqlite`,
74
79
  };
75
80
 
76
81
  for (let i = 0; i < args.length; i++) {
@@ -99,6 +104,13 @@ function parseArgs(): Config {
99
104
  case "-v":
100
105
  config.verbose = true;
101
106
  break;
107
+ case "--db":
108
+ case "--db-sync":
109
+ config.dbSync = true;
110
+ break;
111
+ case "--db-path":
112
+ config.dbPath = args[++i];
113
+ break;
102
114
  case "--help":
103
115
  printHelp();
104
116
  process.exit(0);
@@ -110,10 +122,14 @@ function parseArgs(): Config {
110
122
 
111
123
  function printHelp() {
112
124
  console.log(`
113
- @screenpipe/sync - Extract daily context from Screenpipe
125
+ screenpipe-sync - Extract daily context from Screenpipe
114
126
 
115
127
  USAGE:
116
- bunx @screenpipe/sync [options]
128
+ bunx screenpipe-sync [options]
129
+
130
+ MODES:
131
+ Summary mode (default): AI-powered daily summary extraction
132
+ DB sync mode (--db): Copy raw SQLite database to remote
117
133
 
118
134
  OPTIONS:
119
135
  -o, --output <dir> Save summary to directory (default: stdout)
@@ -123,18 +139,28 @@ OPTIONS:
123
139
  --json Output as JSON instead of markdown
124
140
  -v, --verbose Show debug output
125
141
 
142
+ --db, --db-sync Sync raw SQLite database instead of summary
143
+ --db-path <path> Path to Screenpipe DB (default: ~/.screenpipe/db.sqlite)
144
+
126
145
  ENVIRONMENT:
127
146
  SCREENPIPE_URL Screenpipe API URL (default: http://localhost:3030)
128
- ANTHROPIC_API_KEY Required for AI summarization
147
+ SCREENPIPE_DB Path to Screenpipe database
148
+ ANTHROPIC_API_KEY For AI summarization (or OPENAI_API_KEY)
129
149
 
130
150
  EXAMPLES:
131
- bunx @screenpipe/sync
132
- bunx @screenpipe/sync --output ~/Documents/brain/context --git
133
- bunx @screenpipe/sync --hours 24 --json
134
- bunx @screenpipe/sync --remote clawdbot:~/brain/context
151
+ # AI summary to stdout
152
+ bunx screenpipe-sync
153
+
154
+ # Save daily summaries locally
155
+ bunx screenpipe-sync --output ~/Documents/brain/context --git
135
156
 
136
- OUTPUT:
137
- Creates structured daily summaries with:
157
+ # Sync raw database to remote (e.g., Clawdbot)
158
+ bunx screenpipe-sync --db --remote user@clawdbot:~/.screenpipe/
159
+
160
+ # Full sync: DB + daily summary
161
+ bunx screenpipe-sync --db -r clawdbot:~/.screenpipe && bunx screenpipe-sync -o ~/context -g
162
+
163
+ OUTPUT (summary mode):
138
164
  - Todo items extracted from screen content
139
165
  - Goals and intentions mentioned
140
166
  - Decisions made
@@ -142,6 +168,10 @@ OUTPUT:
142
168
  - Meetings and conversations
143
169
  - Blockers and problems
144
170
  - AI-generated insights
171
+
172
+ OUTPUT (db mode):
173
+ - Copies ~/.screenpipe/db.sqlite to remote
174
+ - Remote can query SQLite directly for full history
145
175
  `);
146
176
  }
147
177
 
@@ -435,10 +465,96 @@ async function writeOutput(content: string, config: Config, filename: string) {
435
465
  // Main
436
466
  // ============================================================================
437
467
 
468
+ async function syncDatabase(config: Config) {
469
+ const fs = await import("fs/promises");
470
+ const { execSync } = await import("child_process");
471
+
472
+ // Check if DB exists
473
+ try {
474
+ await fs.access(config.dbPath);
475
+ } catch {
476
+ console.error(`[error] Database not found at ${config.dbPath}`);
477
+ console.error(` Set --db-path or SCREENPIPE_DB environment variable`);
478
+ process.exit(1);
479
+ }
480
+
481
+ const stats = await fs.stat(config.dbPath);
482
+ const sizeMB = (stats.size / 1024 / 1024).toFixed(1);
483
+ console.error(`[db] Found database: ${config.dbPath} (${sizeMB} MB)`);
484
+
485
+ if (!config.remote && !config.outputDir) {
486
+ console.error(`[error] --db requires --remote or --output to specify destination`);
487
+ process.exit(1);
488
+ }
489
+
490
+ // Copy to local output dir
491
+ if (config.outputDir) {
492
+ const path = await import("path");
493
+ const destDir = path.resolve(config.outputDir);
494
+ await fs.mkdir(destDir, { recursive: true });
495
+ const destPath = path.join(destDir, "db.sqlite");
496
+
497
+ console.error(`[db] Copying to ${destPath}...`);
498
+ await fs.copyFile(config.dbPath, destPath);
499
+
500
+ // Also copy WAL files if they exist (for consistency)
501
+ try {
502
+ await fs.copyFile(`${config.dbPath}-wal`, `${destPath}-wal`);
503
+ await fs.copyFile(`${config.dbPath}-shm`, `${destPath}-shm`);
504
+ } catch {
505
+ // WAL files may not exist, that's ok
506
+ }
507
+
508
+ console.error(`[ok] Database copied to ${destPath}`);
509
+
510
+ if (config.gitPush) {
511
+ try {
512
+ execSync(`cd "${destDir}" && git add -A && git commit -m "db sync $(date +%Y-%m-%d)" && git push`, {
513
+ stdio: config.verbose ? "inherit" : "pipe",
514
+ });
515
+ console.error(`[ok] Git pushed`);
516
+ } catch {
517
+ console.error(`[warn] Git push failed - maybe no changes?`);
518
+ }
519
+ }
520
+ }
521
+
522
+ // Sync to remote
523
+ if (config.remote) {
524
+ console.error(`[db] Syncing to ${config.remote}...`);
525
+ try {
526
+ // Use rsync for efficiency (only transfers changes)
527
+ execSync(`rsync -avz --progress "${config.dbPath}" "${config.remote}/db.sqlite"`, {
528
+ stdio: config.verbose ? "inherit" : "pipe",
529
+ });
530
+ console.error(`[ok] Database synced to ${config.remote}`);
531
+ } catch {
532
+ // Fallback to scp if rsync not available
533
+ try {
534
+ execSync(`scp "${config.dbPath}" "${config.remote}/db.sqlite"`, {
535
+ stdio: config.verbose ? "inherit" : "pipe",
536
+ });
537
+ console.error(`[ok] Database copied to ${config.remote}`);
538
+ } catch (e) {
539
+ console.error(`[error] Failed to sync database: ${e}`);
540
+ process.exit(1);
541
+ }
542
+ }
543
+ }
544
+
545
+ console.error(`[done] Database sync complete`);
546
+ }
547
+
438
548
  async function main() {
439
549
  const config = parseArgs();
440
550
  const today = new Date().toISOString().split("T")[0];
441
551
 
552
+ // DB sync mode
553
+ if (config.dbSync) {
554
+ await syncDatabase(config);
555
+ return;
556
+ }
557
+
442
558
  console.error(`[screenpipe-sync] Analyzing last ${config.hours} hours...`);
443
559
 
444
560
  // 1. Query Screenpipe