| name | screenpipe-cli |
| description | Set up and operate screenpipe from the terminal, including always-on recording, service modes, capture health, storage, local search, read-only SQLite access, pipes, and connections. Use when the user asks to install, run, inspect, query, automate, or debug screenpipe without relying on the desktop app. |
Screenpipe CLI
Run every CLI command exactly like this, from a clean temp directory so bun x cannot collide with a project's node_modules:
cd "$(mktemp -d)" && ${SCREENPIPE_CLI:-bun x screenpipe@latest} <command>
$SCREENPIPE_CLI is an already-resolved native binary that screenpipe publishes and refreshes for you. When it is set, a call costs ~0.15s. The bun x screenpipe@latest fallback runs when it is not (a plain terminal, a fresh install, an offline machine) and costs ~4s, because @latest re-resolves the npm registry every single time. Never replace the whole expression with just bun x screenpipe@latest — you would give up the fast path for no reason.
Rules: every invocation is cd "$(mktemp -d)" && ${SCREENPIPE_CLI:-bun x screenpipe@latest} … · keep the ${SCREENPIPE_CLI:-…} form intact · never drop the cd prefix · copy the examples below verbatim rather than shortening them · because the cd changes your working directory, any path you pass must be absolute (~/... or /...), never relative (./my-pipe).
Works on macOS, Linux, and Windows: the CLI always runs under bash, and mktemp is present on all three (on Windows via the bundled git-portable usr/bin).
Use status, search, and state-changing commands as the canonical terminal surface. For high-frequency read loops, the local REST API is faster (see the screenpipe-api skill), and advanced local workflows may query SQLite read-only.
Sandboxed shells: some agents (e.g. Codex) block all shell network access, so bun x cannot fetch the package and CLI calls to localhost:3030 fail instantly. If that happens, use the screenpipe MCP tools instead of the CLI.
Recorder quickstart
For a CLI-only user who wants this computer recorded continuously, use this sequence:
cd "$(mktemp -d)" && ${SCREENPIPE_CLI:-bun x screenpipe@latest} doctor
cd "$(mktemp -d)" && ${SCREENPIPE_CLI:-bun x screenpipe@latest} service install
cd "$(mktemp -d)" && ${SCREENPIPE_CLI:-bun x screenpipe@latest} status
service install defaults to recorder mode: screen + audio capture, local indexing, and the API, launched at boot/login and restarted after failures. On macOS, resolve Screen Recording, Microphone, and Accessibility permission warnings reported by doctor; a background service cannot bypass OS consent.
Use the foreground process only for an interactive session or live debugging:
cd "$(mktemp -d)" && ${SCREENPIPE_CLI:-bun x screenpipe@latest} record
Use API-only server mode only when the machine should serve existing or synced data without recording itself:
cd "$(mktemp -d)" && ${SCREENPIPE_CLI:-bun x screenpipe@latest} service install --mode server
Running service install again switches modes and restarts the service immediately. service uninstall stops and removes it.
Status and diagnostics
Start every investigation with:
cd "$(mktemp -d)" && ${SCREENPIPE_CLI:-bun x screenpipe@latest} status
This reports the distinction that matters:
recording normally: the API is healthy and at least one capture stream is active
serving normally: intentional server mode; the API is healthy and local capture is disabled
not capturing: the process is up but no capture stream is active
needs attention: the health endpoint reports degraded/unhealthy capture
stopped: no screenpipe health endpoint answered on the selected port
It also prints screen/audio freshness, active devices, history counts, total storage, and the exact SQLite path. Do not infer recording from a PID, an open port, or service status; those prove a process exists, not that new data is arriving.
For scripts and agents, use structured output:
cd "$(mktemp -d)" && ${SCREENPIPE_CLI:-bun x screenpipe@latest} status --json
Important fields are running, health.status, health.frame_status, health.audio_status, last_capture, last_audio_capture, storage_size_bytes, and database_path. Treat running: true as API availability only; inspect capture status and timestamps before claiming recording is healthy.
Useful follow-ups:
cd "$(mktemp -d)" && ${SCREENPIPE_CLI:-bun x screenpipe@latest} service status
cd "$(mktemp -d)" && ${SCREENPIPE_CLI:-bun x screenpipe@latest} doctor
cd "$(mktemp -d)" && ${SCREENPIPE_CLI:-bun x screenpipe@latest} diagnose --dry-run
diagnose --dry-run saves a support bundle locally and does not upload it. Do not run diagnose without --dry-run unless the user explicitly wants to send diagnostics to screenpipe support.
Query local history
search reads the local SQLite database directly and does not require the daemon. Prefer JSON Lines for agent workflows:
cd "$(mktemp -d)" && ${SCREENPIPE_CLI:-bun x screenpipe@latest} search --start "30m ago" --json
cd "$(mktemp -d)" && ${SCREENPIPE_CLI:-bun x screenpipe@latest} search "project alpha" --start "7d ago" --json
cd "$(mktemp -d)" && ${SCREENPIPE_CLI:-bun x screenpipe@latest} search --content-type audio --start "2h ago" --json
cd "$(mktemp -d)" && ${SCREENPIPE_CLI:-bun x screenpipe@latest} search --app "Code" --focused --start "1d ago" --json
Use --limit, --offset, --end, --window, --browser-url, --speaker, and --max-content-length to bound output. An empty result is not evidence that capture is healthy; check status and freshness separately.
Direct SQLite for advanced analysis
The database path is intentionally discoverable through status --json. If the user prefers SQL, open that exact database read-only so SQLite can read the live WAL safely:
status_json="$(cd "$(mktemp -d)" && ${SCREENPIPE_CLI:-bun x screenpipe@latest} status --json)"
db_path="$(printf '%s' "$status_json" | jq -r '.database_path')"
sqlite3 "file:${db_path}?mode=ro" 'PRAGMA query_only=ON; SELECT COUNT(*) FROM frames;'
Never write to the live database, copy only db.sqlite while recording, use immutable=1, or delete -wal/-shm files. Prefer screenpipe search --json unless the analysis genuinely needs SQL.
Shell
- All platforms →
bash (on Windows, the bundled git-portable bash is used automatically)
Note: the bash tool truncates output around ~50 KB. Long listings (connection list, pipe list, etc.) are sorted with connected/enabled rows first, but if you need a specific row, pipe through grep or head rather than scanning the full output — e.g. cd "$(mktemp -d)" && ${SCREENPIPE_CLI:-bun x screenpipe@latest} connection list | grep -E 'browser|connected'.
Pipe Management
Pipes are markdown-based AI automations that run on schedule. Each pipe lives at ~/.screenpipe/pipes/<name>/pipe.md.
Commands
cd "$(mktemp -d)" && ${SCREENPIPE_CLI:-bun x screenpipe@latest} pipe list
cd "$(mktemp -d)" && ${SCREENPIPE_CLI:-bun x screenpipe@latest} pipe enable <name>
cd "$(mktemp -d)" && ${SCREENPIPE_CLI:-bun x screenpipe@latest} pipe disable <name>
cd "$(mktemp -d)" && ${SCREENPIPE_CLI:-bun x screenpipe@latest} pipe run <name>
cd "$(mktemp -d)" && ${SCREENPIPE_CLI:-bun x screenpipe@latest} pipe logs <name>
cd "$(mktemp -d)" && ${SCREENPIPE_CLI:-bun x screenpipe@latest} pipe install <url-or-abs-path>
cd "$(mktemp -d)" && ${SCREENPIPE_CLI:-bun x screenpipe@latest} pipe delete <name>
cd "$(mktemp -d)" && ${SCREENPIPE_CLI:-bun x screenpipe@latest} pipe models list
Creating a Pipe
Create ~/.screenpipe/pipes/<name>/pipe.md with YAML frontmatter + prompt:
---
schedule: every 30m
enabled: true
preset: ["Primary", "Fallback"]
---
Your prompt instructions here. The AI agent executes this on schedule.
## What to do
1. Query screenpipe search API for recent activity
2. Process results
3. Output summary / send notification
Schedule syntax:
- Recurring:
every 30m, every 1h, every day at 9am, every monday at 9am, or cron */30 * * * *, 0 9 * * *
- One-off (fires once, then auto-disables):
at <RFC3339 timestamp> — e.g. at 2026-04-29T17:00:00-07:00
- Manual only:
manual (run via pipe run or API trigger)
One-off scheduled tasks (use this when the user says "in 2 days", "tomorrow at 5pm", "next Monday", "remind me to check X later", or any other future-time deferred action):
---
schedule: at 2026-04-29T17:00:00-07:00
enabled: true
preset: auto
---
Check Gmail for a reply from Mark about the HIPAA evidence pack.
If found, summarize and send a notification. If not, note it.
Resolve "in 2 days" / "tomorrow 5pm" / "next Monday" against the user's local timezone (which is in the context header), format as RFC3339 with offset, and put it in the at <iso> schedule.
When fired, the pipe auto-disables itself — enabled: false is set in the local-overrides file. The pipe.md stays on disk as history. Users see upcoming one-offs in the chat sidebar's "upcoming" section with a countdown ("in 2d 4h"). To cancel before fire time: pipe disable <name>. To re-run after firing: pipe enable <name> then pipe run <name> (or set a new at <iso>).
Config fields: schedule, enabled (bool), preset (string or array — e.g. "Oai" or ["Primary", "Fallback"]), history (bool — include previous output as context)
Screenpipe prepends a context header with time range, timezone, OS, and API URL before each execution. No template variables needed.
After creating:
cd "$(mktemp -d)" && ${SCREENPIPE_CLI:-bun x screenpipe@latest} pipe install ~/.screenpipe/pipes/my-pipe
cd "$(mktemp -d)" && ${SCREENPIPE_CLI:-bun x screenpipe@latest} pipe enable my-pipe
cd "$(mktemp -d)" && ${SCREENPIPE_CLI:-bun x screenpipe@latest} pipe run my-pipe
Testing from in-app chat
The cloud JWT is intentionally absent from Bash. Do not expose or recover it, and do not use standalone pipe run. Test through the authenticated desktop runtime:
api="${SCREENPIPE_LOCAL_API_URL:-http://localhost:3030}"
auth="Authorization: Bearer $SCREENPIPE_LOCAL_API_KEY"
curl -sS -X POST -H "$auth" "$api/pipes/my-pipe/run"
curl -sS -H "$auth" "$api/pipes/my-pipe/logs"
{"success":true} means the run started, not that it passed. Poll for a new terminal log. Bind only after success: true; otherwise report its stderr and leave the Live View unchanged.
Editing Config
Edit frontmatter in ~/.screenpipe/pipes/<name>/pipe.md directly, or use the API:
curl -X POST http://localhost:3030/pipes/<name>/config \
-H "Content-Type: application/json" \
-d '{"config": {"schedule": "every 1h", "enabled": true}}'
Output & Artifacts
Pipes can produce user-facing output files that appear in the Artifacts library.
Standard path — for files inside the pipe directory:
External path — for files outside the pipe directory (shared locations, user folders, vaults):
Rules
- Use
pipe list (not --json) — table output is compact
- Never dump full pipe JSON — can be 15MB+
- Check logs first when debugging:
pipe logs <name>
- Outside in-app chat, use
pipe run <name> before waiting for a schedule; in-app chat uses the authenticated runtime above
Connection Management
Manage integrations (Telegram, Slack, Discord, Email, Todoist, Teams) from the CLI.
Commands
cd "$(mktemp -d)" && ${SCREENPIPE_CLI:-bun x screenpipe@latest} connection list
cd "$(mktemp -d)" && ${SCREENPIPE_CLI:-bun x screenpipe@latest} connection list --json
cd "$(mktemp -d)" && ${SCREENPIPE_CLI:-bun x screenpipe@latest} connection get <id>
cd "$(mktemp -d)" && ${SCREENPIPE_CLI:-bun x screenpipe@latest} connection get <id> --json
cd "$(mktemp -d)" && ${SCREENPIPE_CLI:-bun x screenpipe@latest} connection set <id> key=val
cd "$(mktemp -d)" && ${SCREENPIPE_CLI:-bun x screenpipe@latest} connection test <id>
cd "$(mktemp -d)" && ${SCREENPIPE_CLI:-bun x screenpipe@latest} connection remove <id>
Examples
cd "$(mktemp -d)" && ${SCREENPIPE_CLI:-bun x screenpipe@latest} connection set telegram bot_token=123456:ABC-DEF chat_id=5776185278
cd "$(mktemp -d)" && ${SCREENPIPE_CLI:-bun x screenpipe@latest} connection set slack webhook_url=https://hooks.slack.com/services/...
cd "$(mktemp -d)" && ${SCREENPIPE_CLI:-bun x screenpipe@latest} connection test telegram
cd "$(mktemp -d)" && ${SCREENPIPE_CLI:-bun x screenpipe@latest} connection list
Connection IDs: telegram, slack, discord, email, todoist, teams, google-calendar, openclaw
Credentials are stored locally and are not printed by connection get.
Per-integration details: don't guess API shapes from this skill. Run connection list for self-describing local endpoints. connection get <id> returns only status and non-secret settings.
Publishing pipes to the store
screenpipe pipe publish <pipe-name>
Reads ~/.screenpipe/pipes/<pipe-name>/pipe.md, extracts title/description/icon/category from YAML frontmatter, and publishes to the screenpipe pipe store. Requires auth (SCREENPIPE_API_KEY env var or ~/.screenpipe/auth.json).