Lines 86-160javascript
86// 4. CLI via PATH-based npx — last CLI fallback.
87// 5. Direct sqlite3 read of ~/.screenpipe/db.sqlite — plaintext entries
88// only (encrypted entries need the keychain, which only the CLI can
89// reach). Kept as a final last-resort for users who have screenpipe
90// *data* but no working CLI install (rare). Demoted below the CLI
91// paths because it reimplements logic that lives in `auth_key.rs` and
92// can silently drift on storage-format changes.
94// If all 5 miss we log a loud stderr warning so it surfaces in the host's
95// MCP log instead of the user just seeing 403s with no explanation.
96function discoverApiKey() {
97 const envKey = process.env.SCREENPIPE_LOCAL_API_KEY || process.env.SCREENPIPE_API_KEY;
100 // eslint-disable-next-line @typescript-eslint/no-var-requires
101 const os = require("os");
102 // eslint-disable-next-line @typescript-eslint/no-var-requires
103 const path = require("path");
104 // eslint-disable-next-line @typescript-eslint/no-var-requires
105 const fs = require("fs");
106 // eslint-disable-next-line @typescript-eslint/no-var-requires
107 const { execFileSync, execSync } = require("child_process");
108 const home = os.homedir();
109 // 2. CLI via bundled `bun` shipped with the desktop app. The Tauri
110 // externalBin config places `bun` next to the main app exe at a
111 // deterministic install path on each OS, so we don't need PATH —
112 // which Claude Desktop's MCP launcher strips. The CLI's `auth
113 // token` goes through `find_api_auth_key` and decrypts via
114 // keychain when needed.
115 const bunCandidates = process.platform === "darwin"
117 // Standard system-wide install
118 "/Applications/screenpipe.app/Contents/MacOS/bun",
120 path.join(home, "Applications", "screenpipe.app", "Contents", "MacOS", "bun"),
122 : process.platform === "win32"
124 // NSIS per-user (default on Windows)
125 path.join(home, "AppData", "Local", "screenpipe", "bun.exe"),
126 // Per-user under "screenpipe-app" (older builds)
127 path.join(home, "AppData", "Local", "screenpipe-app", "bun.exe"),
128 // System-wide install
129 "C:\\Program Files\\screenpipe\\bun.exe",
133 "/opt/screenpipe/bun",
134 "/usr/lib/screenpipe/bun",
137 for (const bunPath of bunCandidates) {
138 if (!fs.existsSync(bunPath))
141 const token = execFileSync(bunPath, ["x", "screenpipe@latest", "auth", "token"], {
142 timeout: 30000, // first run downloads the package; subsequent runs are cached
144 stdio: ["pipe", "pipe", "pipe"],
146 if (token && token.startsWith("sp-"))
150 // try next candidate
153 // 3. CLI via npx adjacent to the running node. Works for dev
154 // environments without the desktop app.
HighRuntime Package Install
Package source invokes a package manager install command at runtime.
dist/index.jsView on unpkg · L140 156 const npxName = process.platform === "win32" ? "npx.cmd" : "npx";
157 const npxPath = path.join(path.dirname(process.execPath), npxName);
158 if (fs.existsSync(npxPath)) {
159 const token = execFileSync(npxPath, ["screenpipe@latest", "auth", "token"], {