screenpipe-api について
Screenpipe のローカル REST API を利用するためのガイドです。画面、音声、アクティビティを取得する Agent やスクリプト向けに、検索、要約、タグ付け、同期デバイスの照会、応答サイズの調整方法を説明します。
主な機能
- 01画面・音声・解析データの検索
- 02期間を指定したアクティビティ要約
- 03タグによる記録とメモの関連付け
- 04同期デバイスの照会
- 05形式やフィールドによる応答縮小
活用シーン
- 01指定期間の画面や音声の記録を検索
- 02アプリやウィンドウごとの活動を確認
- 03人物やプロジェクトに関連する記録を取得
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ screenpipe/ screenpipe --skill screenpipe-apiインストール後、Claude Code で/screenpipe-apiを入力して読み込まれたか確認します。
詳細
Screenpipe API
http://localhost:3030 のローカル REST API です。完全なリファレンス(60 以上のエンドポイント):https://docs.screenpi.pe/llms-full.txt
認証
すべてのリクエストで認証が必要です。 すべての curl 呼び出しに認証ヘッダーを追加してください。
curl -H "Authorization: Bearer $SCREENPIPE_LOCAL_API_KEY" \
-H "X-Screenpipe-Client: api" \
-H "X-Screenpipe-Agent: unknown" \
"http://localhost:3030/..."
固定値 X-Screenpipe-Client: api は、成功した空でない外部からの取得を API サーフェスに帰属させるためのものです。このヘッダーには、エージェント名、顧客名、プロジェクト、プロンプト、その他の動的な値を絶対に含めないでください。
REST での取得では、上記の両方の帰属ヘッダーを含めてください。インストーラーは X-Screenpipe-Agent に固定のアプリ識別子を設定します。その値は変更せずに保持してください。未設定の参照の場合は、unknown のままにしてください。プロジェクト、ユーザー、モデル、プロンプト、その他の動的な識別子で置き換えないでください。
$SCREENPIPE_LOCAL_API_KEY 環境変数はすでに環境に設定されています。設定されていない場合は 403 が返ります。例外は /health のみで、認証は不要です。
コンテキストウィンドウの保護
API のレスポンスは大きくなる場合があります。curl の出力は必ず最初にファイルへ書き込み(curl ... -o /tmp/sp_result.json)、サイズを確認し(wc -c /tmp/sp_result.json)、5KB を超える場合は先頭 50~100 行だけを読み取ってください。必要な情報は jq で抽出してください。大きなレスポンス全体をコンテキストに出力することは絶対に避けてください。
リストエンドポイント(/search、/elements、/frames/{id}/elements)では、取得元でトークン数をさらに削減できます。&format=csv(または tsv)を追加すると、各行でキーを繰り返さず、列名を一度だけ記載した表形式で取得できます。また、&fields=a,b,c を指定すると、必要な列だけを返します(content.text のようなドット区切りのパスも指定できます)。UI 要素のリストでは、JSON と比べてトークン数をおよそ 70% 削減できます。特に要素エンドポイントでは、&format=outline(別名 tree)を指定すると、テキストを含むノードのみを重複排除してインデント表示するため、さらに削減できます(実測で約 91% 減)。UI 構造を読み取る際には、これが最適なデフォルトです。自動化の計画には &format=automation を使用してください。これには、対話型コントロール、状態、境界、許可されたアクション、レスポンス内で短く参照できる ID、最善努力による安定キーが保持されます。テキスト量の多い ocr/audio では、テキストの塊が大部分を占めるため、形式を変更してもほとんど効果はありません。その場合は fields と max_content_length を使用してください。format/fields を指定しない場合、レスポンスは変更されず JSON のままです。
1. 検索 — GET /search
curl -H "Authorization: Bearer $SCREENPIPE_LOCAL_API_KEY" \
-H "X-Screenpipe-Client: api" \
-H "X-Screenpipe-Agent: unknown" \
"http://localhost:3030/search?q=QUERY&content_type=all&limit=10&start_time=1h%20ago"
パラメーター
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
q | string | いいえ | キーワード。音声検索には使用しないでください。文字起こしにはノイズが多く、q のフィルターは絞り込みが強すぎます。 |
content_type | string | いいえ | all(デフォルト)、accessibility、audio、input、ocr、memory、parsed。アプリ固有の簡潔なメッセージ、メール、タスク、ドキュメント、コードレビューには parsed を使用してください。解析キャプチャは実験的な機能です。無効または非対応の場合は空になることがあり、all には含まれません。画面上のテキストは主に OS のアクセシビリティツリー(accessibility)経由で取得されます。OCR はアクセシビリティに対応していないアプリ用のフォールバックです。 |
limit | integer | いいえ | 最大 1~20。デフォルト:10 |
offset | integer | いいえ | ページネーション。デフォルト:0 |
start_time | ISO 8601、相対指定、またはローカルカレンダー | はい | 2024-01-15T10:00:00Z、16h ago、today、yesterday、または YYYY-MM-DD を指定できます |
end_time | start_time と同じ | いいえ | デフォルトは now です |
app_name | string | いいえ | 例:「Google Chrome」、「Slack」、「zoom.us」 |
window_name | string | いいえ | ウィンドウタイトルの部分文字列 |
frame_id | integer | いいえ | content_type=parsed の場合、1 つのフレームに紐づく解析データを返します。 |
actor_id | integer | いいえ | content_type=parsed の場合、解決済みのアクター ID でフィルタリングします。 |
speaker_name | string | いいえ | 音声を話者でフィルタリングします(大文字と小文字を区別しない部分一致) |
focused | boolean | いいえ | フォーカス中のウィンドウのみ |
tags | string | いいえ | カンマ区切り。指定したタグをすべて持つアイテムのみを返します(例:person:ada,project:atlas)。画面/音声に加え、content_type=memory の場合はメモリーにも使用できます。下記のタグを参照してください。 |
include_related | boolean | いいえ | tags を指定すると、関連タグ(指定したタグと一緒に確認された人/プロジェクト/ワークフロー)の related マップも返します。頻度の高い順に並びます。複数回呼び出さずに周辺のコンテキストを取得できます。下記のタグを参照してください。 |
max_content_length | integer | いいえ | 各結果のテキストを切り詰めます(中央部分を省略) |
format | string | いいえ | json(デフォルト)、csv、tsv/table、または outline/tree(要素エンドポイントのみ)。CSV/TSV は、行ごとに JSON オブジェクトを返す代わりに、列名を一度だけ記載した表形式データを返します。outline は、テキストを含む UI ノードを重複排除したインデント付きテキストツリーとして返します。「画面には何が表示されていますか?」を確認する際に最もコストが低い方法です(トークンを約 91%削減)。CSV は情報を損失しません。TSV は改行をまとめるため、長い ocr テキストには適しません。 |
fields | string | いいえ | ドット区切りパスで指定する、カンマ区切りの列許可リストです。例:type,content.app_name,content.text。指定した列のみを返します(繰り返し出力される絶対パスの content.file_path を除外するのに便利です)。json にも対応しています(疎なオブジェクト)。 |
段階的な開示
重い /search 呼び出しにいきなり進まないでください。次の順に段階を進めてください。
| ステップ | エンドポイント | 使用する場面 |
|---|---|---|
| 0 | GET /memories?q=... | 必ず最初に、または並行してクエリします — 最も有用な情報が得られ、コストが最も低い方法です |
| 1 | GET /activity-summary?start_time=...&end_time=... | 大まかな質問(「何をしていましたか?」「どのアプリを使っていましたか?」) |
| 2 | GET /search?... | 特定のコンテンツが必要な場合 |
| 3 | GET /elements?... または GET /frames/{id}/context | UI の構造、ボタン、リンク |
| 4 | GET /frames/{frame_id}(PNG) | 視覚的なコンテキストが必要な場合 |
判断ツリー:
- 「何をしていましたか?」→ ステップ 1 のみ
- 「会議を要約して」→
content_type=audioを指定してステップ 2。q パラメーターは指定しないでください。画面上のコンテキストも必要な場合はcontent_type=allを追加します。 - 「X にどれくらい時間を使いましたか?」→ ステップ 1(
/activity-summary→ 対象期間全体のtotal_active_minutesと、アプリ/ウィンドウ別のminutes) - 「今日使ったアプリは?」→ ステップ 1(フレーム数や SQLite の生データは使用しないでください)
- 「どのボタンをクリックしましたか?」→ ステップ 3(
role=AXButtonを指定して/elements) - 「見ていた画面を表示して」→ ステップ 2(frame_id を検索)→ ステップ 4
添付されたアクティビティエピソード
チャットメッセージには、正確な時間範囲と引用された画面、音声、または会議のアーティファクトを含む [Context from activity episode: ...] が含まれることがあります。これらの値は検索の基点として扱ってください。アクティビティのタイトルと概要は生成されたラベルであり、記録されたコンテンツでも検索語でもありません。
- エピソードの詳細、要点、決定事項、または原因について質問された場合は、回答する前に元のコンテンツを取得してください。正確な時間範囲から開始し、
qは指定しないでください。引用された画面は/frames/{frame_id}/contextで調べ、引用された音声はcontent_type=audioで検索し、会議のトランスクリプトには引用された会議 ID を使用するか、複数ソースにまたがる期間にはcontent_type=allで検索してください。 - アクティビティのタイトルや概要から
qを導き出してはいけません。ユーザーが特定の単語やフレーズそのものを探すよう明示的に求めた場合に限り、qを使用してください。 - 取得したコンテンツを分析してください。生成された概要をそのまま言い換えるだけにしてはいけません。
タグ — 人、プロジェクト、トピックの関連付け
タグは、画面、音声、メモリ全体で共有される、単一の文字列名前空間を持つラベルレイヤーです。名前空間付きタグを使用してください:person:ada、project:atlas、topic:pricing。2つのアイテムに同じタグが付いている場合、それらは関連付けられます。
- フレーム/音声に追加する場合:
POST /tags/vision/{frame_id}またはPOST /tags/audio/{chunk_id}を使用し、本文には{"tags":["person:ada"]}を指定します。 - メモリに追加する場合:
POST /memories(またはPUT /memories/{id})にtagsを含めます。 - タグで取得する場合:
GET /search?tags=person:ada&start_time=30d%20ago(画面+音声)を使用します。メモリを検索するにはcontent_type=memoryを追加します。複数のタグは AND 条件で扱われ、一致判定は完全一致で、部分文字列は対象外です。
フレームは保持ポリシーに従って削除されるため、長期的に残る関連付けにはメモリにタグを付けてください(メモリには created_at と、その時点に戻るための frame_id も記録されます。GET /frames/{frame_id} で移動できます)。ある人物について全期間の情報を取得するには、記録データ用に content_type=all&tags=person:ada、事実データ用に content_type=memory&tags=person:ada をそれぞれ1回呼び出します。
タグ検索に include_related=true を追加すると、同じ応答内で周辺コンテキストを取得できます。自身のタグと共起するタグが、名前空間ごとにグループ化され(接頭辞は複数形になります:person:→people、project:→projects)、頻度順に並びます。これにより、「ほかに誰/何があるか」を尋ねる追加呼び出しを2〜3回行う必要がなくなります:
curl -H "Authorization: Bearer $SCREENPIPE_LOCAL_API_KEY" \
"http://localhost:3030/search?tags=person:ada&include_related=true&limit=5"
# data: [...], related: { "people": ["connor","drew"], "projects": ["atlas"], "workflows": ["planning"] }
重要なルール
カレンダーの日付範囲はローカル時間です: today、yesterday、および日付のみの YYYY-MM-DD は、UTC の日付や直近24時間ではなく、ユーザーのタイムゾーンにおけるローカルの暦日を意味します。カレンダー日付のリテラルを API に直接渡してください(start_time=today&end_time=now、start_time=yesterday&end_time=today)。date -u で午前0時を計算したり、T00:00:00Z を追加したりしてはいけません。
- 必ず
start_timeを含めてください — 時間範囲を指定しないクエリはタイムアウトします - 1〜2時間の範囲から開始してください — 結果がない場合にのみ範囲を広げます
- ユーザーが特定のアプリに言及した場合は
app_nameを使用してください - 最初は
limitを小さく(5〜10)設定してください - 「最近」 = 30分
- タイムアウトした場合は、時間範囲を狭めてください
応答形式
{
"data": [
{"type": "OCR", "content": {"frame_id": 12345, "text": "...", "timestamp": "...", "app_name": "Chrome", "window_name": "..."}},
{"type": "Audio", "content": {"chunk_id": 678, "transcription": "...", "timestamp": "...", "speaker": {"name": "John"}}},
{"type": "UI", "content": {"id": 999, "text": "Clicked 'Submit'", "timestamp": "...", "app_name": "Safari"}},
{"type": "Parsed", "content": {"frame_id": 12345, "text": "compact corrected app data", "items": [], "actors": []}}
],
"pagination": {"limit": 10, "offset": 0, "total": 42}
}
注記:
"OCR"タイプのラベルは、アクセシビリティツリー経由で取得したテキストを含む、すべての画面テキストの結果に使用されます。画面テキストの大半は OCR ではなく、アクセシビリティ機能から取得されます。
同期済みデバイス — GET /data-sync/devices および GET /data-sync/search
ユーザーが別のデバイス、デバイス間と言った場合、または現在のデバイス以外のマシンを指定した場合は、これらのエンドポイントを使用してください。現在のマシンのみを対象とする場合は、引き続き /search を使用してください。こちらのほうが高速で、ローカルフィルターも充実しています。
curl -H "Authorization: Bearer $SCREENPIPE_LOCAL_API_KEY" \
"http://localhost:3030/data-sync/devices"
curl -H "Authorization: Bearer $SCREENPIPE_LOCAL_API_KEY" \
"http://localhost:3030/data-sync/search?device_name=MacBook&since_hours_ago=24&q=pricing&limit=10"
デバイス名が曖昧な場合は、/data-sync/devices から開始してください。検索では q、device_name、device_id、app_name、since、until、since_hours_ago、および limit を指定できます。返されたデバイスとタイムスタンプを引用してください。Data Sync が無効または利用できない場合は、その旨を明確に伝えてください。クラウドトークン、アカウント ID、ユーザー ID、または R2 バケットを求めてはいけません。また、R2 に直接アクセスしてはいけません。ローカル API がサインイン済みの ID を提供します。
2. アクティビティの概要 — GET /activity-summary
curl -H "Authorization: Bearer $SCREENPIPE_LOCAL_API_KEY" \
-H "X-Screenpipe-Client: api" \
-H "X-Screenpipe-Agent: unknown" \
"http://localhost:3030/activity-summary?start_time=1h%20ago&end_time=now"
次の情報を含む詳細な概要を返します。
- total_active_minutes:指定範囲全体の、アクティブな画面使用時間の確定合計(すべてのアプリが対象。アイドル時間は除外)。総計/分母として使用してください。
windows[].minutes(最大30分に制限されています)を合計しないでください。また、時間を再計算するためにdb.sqliteを開かないでください。このフィールドがすでに答えです。 - apps:アプリごとの
minutes(アクティブ時間)、最初/最後に確認された時刻 - windows:タイトル、
browser_url、使用時間を示すminutesを含む、個別のウィンドウ/タブすべて。「ユーザーが何に取り組んでいたか」を知るうえで最も有用なフィールドです(時間上位30件)。 - key_texts:ウィンドウのコンテキストごとに代表的なテキストスニペットを1つ(静的なページテキストより、ユーザー入力欄を優先)
- audio_summary.top_transcriptions:話者とタイムスタンプを含む実際の文字起こしテキスト(件数だけではありません)
通常、追加検索をしなくても「何をしていたか?」に答えるにはこれで十分です。逐語的な引用や特定のコンテンツが必要な場合に限り、/searchを掘り下げてください。
パイプ/自動化を構築していますか? 時間の計算には、同じルールを適用してください。このエンドポイントを呼び出してください。数値はフレームのタイムスタンプからサーバー側で計算されます。生のフレームから時間を再計算したり、LLMに分数の合計を求めたりしないでください(ずれが生じます)。アクティビティのラベル付けはモデルに任せ、時間の計算はこのエンドポイントに任せてください。
3. 要素 — GET /elements
UI 要素を対象とする軽量なFTS検索です(各要素は約100~500バイトで、/searchの5~20KBに比べて小容量です)。
curl -H "Authorization: Bearer $SCREENPIPE_LOCAL_API_KEY" "http://localhost:3030/elements?q=Submit&start_time=1h%20ago&limit=10"
パラメーター:q、frame_id、source(accessibility|ocr)、role、start_time、end_time、app_name、limit、offsetに加え、format(json/csv/tsv/outline/automation)とfields(ドット区切りのパス)。要素は均一な行形式なので、簡潔な形式が最も効果を発揮します。
「画面に何が表示されているか?」を知るには、format=outline(別名tree)が最も低コストです。 — テキストを持つノードだけをまとめた、重複排除済みのインデント付きテキストツリーです(空の構造ノードと境界情報を除外し、繰り返しを×Nにまとめます。#idは参照IDです。(disabled)/(selected)/(focused)/(expanded)/(off-screen)の状態をインライン表示し、本文には上限があります)。source=accessibility(よくあるUIケースで、構造上のノイズ、繰り返し行、階層、状態を含みます)で最も効果的です。JSONに比べてトークン数を85~99%削減できます(o200k_base)。フラットなOCRテキストブロックは削減の下限です(重複排除できるものがありません)。OCRのみの場合は、format=csv&fields=textがほぼ最適です。
# compact outline — best default for an LLM reading the UI
curl -H "Authorization: Bearer $SCREENPIPE_LOCAL_API_KEY" "http://localhost:3030/elements?q=Submit&format=outline&limit=30"
# frame 12345 · accessibility · 8 text elements
# AXButton "Submit Order" #4012
# AXButton "Cancel" #4013 (disabled)
# AXCell "Shipped" #4020 ×6
# columnar table when you need specific columns (e.g. bounds) instead
curl -H "Authorization: Bearer $SCREENPIPE_LOCAL_API_KEY" "http://localhost:3030/elements?frame_id=12345&format=csv&fields=role,text,bounds.left,bounds.top"
GET /frames/{id}/elements?format=outlineを使うと、同じ方法でフレーム全体のツリーを取得できます(上限があるため、生のJSONダンプとは異なります)。
format=automationは自動化の構造向けであり、記憶向けではありません。 スナップショットのリビジョン、短いref=eNハンドル、ベストエフォートのkey=k_*識別子、キーの品質、状態、正規化された境界情報、許可されたアクションを出力します。アクションを実行する前に、必ず再取得してください。ベストエフォートのキーは一致を示す証拠であり、実行の許可ではありません。キー、ロール、名前、境界情報を確認し、key_quality=ambiguousの場合は中止してください。format=preferredはデスクトップAIのコンテキスト設定に従います。デフォルト設定では、読み取り/記憶用のアウトラインが維持されます。
curl -H "Authorization: Bearer $SCREENPIPE_LOCAL_API_KEY" "http://localhost:3030/frames/12345/elements?format=automation"
フレームのコンテキスト — GET /frames/{id}/context
フレームのアクセシビリティテキスト、解析済みノード、抽出されたURLを返します。
curl -H "Authorization: Bearer $SCREENPIPE_LOCAL_API_KEY" "http://localhost:3030/frames/6789/context"
よく使われるロール(プラットフォーム固有)
ロールはプラットフォーム間で正規化されていません。ユーザーのOSに合った形式を使用してください。
| 概念 | macOS | Windows | Linux |
|---|---|---|---|
| ボタン | AXButton | Button | Button |
| 静的テキスト | AXStaticText | Text | Label |
| リンク | AXLink | Hyperlink | Link |
| テキストフィールド | AXTextField | Edit | Entry |
| テキストエリア | AXTextArea | Document | Text |
| メニュー項目 | AXMenuItem | MenuItem | MenuItem |
| チェックボックス | AXCheckBox | CheckBox | CheckBox |
| グループ | AXGroup | Group | Group |
| Web領域 | AXWebArea | Pane | DocumentWeb |
| 見出し | AXHeading | Header | Heading |
| タブ | AXTab | TabItem | Tab |
| リスト項目 | AXRow | ListItem | ListItem |
OCRのみのロール(アクセシビリティが利用できない場合のフォールバック):line、word、block、paragraph、page
4. フレーム(スクリーンショット) — GET /frames/{frame_id}
curl -o /tmp/frame.png "http://localhost:3030/frames/12345"
PNG をそのまま返します。1 回のクエリで取得するフレームは 2~3 枚までにしてください(各約 1,000~2,000 トークン)。
5. メディアのエクスポート — POST /export
リアルタイム MP4 をレンダリングします(実際のタイムスタンプの画面フレームと同期したマイク音声)。クリップの長さは指定した実時間の範囲と一致します。早送りのタイムラプスではありません。
curl -X POST http://localhost:3030/export \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $SCREENPIPE_LOCAL_API_KEY" \
-d '{"start": "5m ago", "end": "now"}'
フィールド:start と end(ISO 8601、または "2h ago"、"now" のような相対指定。end のデフォルトは現在時刻)、または会議全体をエクスポートする場合は meeting_id を指定します。output_path は任意で指定でき、MP4 を特定の絶対パス(例:~/Downloads/clip.mp4)に書き込みます。指定しない場合は、データディレクトリ内の exports/ フォルダーに保存されます。
{"output_path": "...", "frame_count": N, "audio_chunk_count": N, "duration_secs": N, "file_size_bytes": N} を返します。再生用に output_path をインラインコードブロックで表示してください。長い範囲では数分かかることがあります。
オーディオと ffmpeg
検索結果のオーディオファイル(file_path)。一般的な操作:
ffmpeg -y -i /path/to/audio.mp4 -q:a 2 ~/.screenpipe/exports/output.mp3 # convert
ffmpeg -y -i input.mp4 -ss 00:01:00 -to 00:05:00 -q:a 2 clip.mp3 # trim
ffmpeg -y -i input.mp4 -filter:v "setpts=0.5*PTS" -an fast.mp4 # speed 2x
ffmpeg -y -i input.mp4 -t 10 -vf "fps=10,scale=640:-1" output.gif # GIF
必ず -y を使用し、~/.screenpipe/exports/ に保存してください。
6. 再文字起こし — POST /audio/retranscribe
curl -X POST http://localhost:3030/audio/retranscribe \
-H "Content-Type: application/json" \
-d '{"start": "1h ago", "end": "now"}'
任意の項目:engine(whisper-large-v3-turbo|whisper-large-v3|deepgram|qwen3-asr)、vocabulary(バイアス付与/置換用の {"word": "...", "replacement": "..."} の配列)、prompt(Whisper 用のトピックコンテキスト)。
範囲は短くしてください(最大 1 時間)。変更前と変更後の文字起こしを表示してください。
7. 生 SQL — POST /raw_sql
curl -X POST http://localhost:3030/raw_sql \
-H "Content-Type: application/json" \
-d '{"query": "SELECT ... LIMIT 100"}'
ルール:すべての SELECT に LIMIT が必要です。常に時間で絞り込んでください。読み取り専用です。時刻計算については、以下のタイムスタンプに関する注意事項を参照してください。
タイムスタンプに関する注意事項:DB のタイムスタンプは RFC3339 形式の文字列として保存されます。通常は 2026-06-26T18:01:14.214586+00:00 です(frames / audio_transcriptions / ui_events)。一方、一部のテーブル(例:meetings.meeting_start、memories)では、ミリ秒付きの Z サフィックスを使用します:2026-06-26T18:01:14.214Z。どちらの形式も SQLite の datetime() 文字列(例:timestamp > datetime('now', '-10 seconds'))と直接比較しないでください。T とスペースの違いにより辞書順の文字列比較となり、同日の古い行が含まれる場合があります。datetime(timestamp) > datetime('now', '-10 seconds') を使用してください(どちらの形式でも動作します)。インデックスを使った文字列比較には、RFC3339 形式のカットオフを使用してください:timestamp > strftime('%Y-%m-%dT%H:%M:%f+00:00', 'now', '-10 seconds')。
警告:時間の推定にフレーム数を使用しないでください。フレームはイベント駆動型であり、固定間隔ではありません。画面表示時間には /activity-summary を使用してください。
スキーマ
| テーブル | 主な列 | 時刻列 |
|---|---|---|
frames | app_name、window_name、browser_url、focused | timestamp |
ocr_text | text、app_name、window_name | frame_id 経由で結合 |
elements | source、role、text、bounds_* | frame_id 経由で結合 |
audio_transcriptions | transcription、device、speaker_id、is_input_device | timestamp |
audio_chunks | file_path | timestamp |
speakers | name、metadata | — |
ui_events | event_type、app_name、window_title、browser_url | timestamp |
accessibility | app_name、window_name、text_content、browser_url | timestamp |
meetings | meeting_app、title、attendees、detection_source | meeting_start |
memories | content、source、tags、importance | created_at |
クエリの例
-- Most used apps (last 24h)
SELECT app_name, COUNT(*) as frames FROM frames
WHERE timestamp > strftime('%Y-%m-%dT%H:%M:%f+00:00', 'now', '-24 hours') AND app_name IS NOT NULL
GROUP BY app_name ORDER BY frames DESC LIMIT 20
-- Most visited domains
SELECT CASE WHEN INSTR(SUBSTR(browser_url, INSTR(browser_url, '://') + 3), '/') > 0
THEN SUBSTR(SUBSTR(browser_url, INSTR(browser_url, '://') + 3), 1, INSTR(SUBSTR(browser_url, INSTR(browser_url, '://') + 3), '/') - 1)
ELSE SUBSTR(browser_url, INSTR(browser_url, '://') + 3) END as domain,
COUNT(*) as visits FROM frames
WHERE timestamp > strftime('%Y-%m-%dT%H:%M:%f+00:00', 'now', '-24 hours') AND browser_url IS NOT NULL
GROUP BY domain ORDER BY visits DESC LIMIT 20
-- Speaker stats
SELECT COALESCE(NULLIF(s.name, ''), 'Unknown') as speaker, COUNT(*) as segments
FROM audio_transcriptions at LEFT JOIN speakers s ON at.speaker_id = s.id
WHERE at.timestamp > strftime('%Y-%m-%dT%H:%M:%f+00:00', 'now', '-24 hours')
GROUP BY at.speaker_id ORDER BY segments DESC LIMIT 20
-- Context switches per hour
SELECT strftime('%H:00', timestamp) as hour, COUNT(*) as switches
FROM ui_events WHERE event_type = 'app_switch' AND timestamp > strftime('%Y-%m-%dT%H:%M:%f+00:00', 'now', '-24 hours')
GROUP BY hour ORDER BY hour LIMIT 24
よく使われるパターン:GROUP BY date(timestamp)(日単位)、GROUP BY strftime('%H:00', timestamp)(時間単位)、HAVING frames > 5(ノイズを除外)。
8. 接続 — GET /connections
# List all integrations (Telegram, Slack, Discord, Email, Todoist, Teams, 40+)
curl http://localhost:3030/connections
# Get connection status and non-secret settings
curl http://localhost:3030/connections/telegram
接続情報の読み取りでは、ステータスと宣言済みの非機密設定のみを返します。保存されたシークレットが API レスポンスに含まれることはありません。専用のローカルエンドポイントまたはプロキシを使用してください。
- Telegram:
{"text":"..."}を指定してPOST /connections/telegram/send - n8n / Zapier / Make:任意の JSON を指定して
POST /connections/<id>/proxy - Discord:
{"content":"..."}を指定してPOST /connections/discord/proxy - Teams webhook:
{"text":"..."}を指定してPOST /connections/teams/proxy
API プロキシ連携 — 認証情報はサーバー側に保存されます。ローカルのワイルドカードプロキシを呼び出すと、認証情報が挿入され、上流 API に転送されます。
# GitHub — create an issue (repo owner/name from pipe settings)
curl -X POST http://localhost:3030/connections/github/proxy/repos/OWNER/REPO/issues \
-H "Content-Type: application/json" \
-d '{"title":"Found a bug","body":"Steps to reproduce..."}'
# GitHub — comment on an issue
curl -X POST http://localhost:3030/connections/github/proxy/repos/OWNER/REPO/issues/42/comments \
-H "Content-Type: application/json" \
-d '{"body":"Thanks for the report!"}'
# Generic OAuth proxy pattern (Zoom, Vercel, Google Docs, Microsoft 365, etc.)
curl -X POST http://localhost:3030/connections/<id>/proxy/<upstream-api-path> \
-H "Content-Type: application/json" \
-d '{...}'
パイプから https://api.github.com/... を直接呼び出さないでください。代わりに /connections/github/proxy/... を使用してください。/connections/<id>/token エンドポイントはありません。
接続されていない場合は、デスクトップアプリの「Connections」ページで設定するようユーザーに伝えてください。
9. ミーティング — GET /meetings、PUT /meetings/:id
curl -H "Authorization: Bearer $SCREENPIPE_LOCAL_API_KEY" "http://localhost:3030/meetings?start_time=1d%20ago&end_time=now&limit=10&offset=0"
curl -H "Authorization: Bearer $SCREENPIPE_LOCAL_API_KEY" "http://localhost:3030/meetings?q=alice%40acme.com"
curl -H "Authorization: Bearer $SCREENPIPE_LOCAL_API_KEY" "http://localhost:3030/meetings/42"
# Update mutable fields. This is a partial update body: omitted fields stay as-is.
curl -X PUT http://localhost:3030/meetings/42 \
-H "Authorization: Bearer $SCREENPIPE_LOCAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{"title":"Q3 planning", "note":"<existing note>\n\n## Summary\n<summary>"}'
検出されたミーティングを返します(カレンダー、アプリの検出、ウィンドウタイトル、UI 要素、複数話者の音声から)。q はタイトル、参加者、メモを対象とする、大文字と小文字を区別しない部分文字列フィルターです。
ミーティングの更新には PATCH ではなく PUT /meetings/:id を使用します。AI が生成した要約を追記する前に、まず現在のミーティングを読み込み、ユーザーが作成したメモを保持できるよう、既存の note テキストを新しいメモ本文に含めてください。
| フィールド | 型 | 説明 |
|---|---|---|
id | 整数 | ミーティング ID |
meeting_start | ISO 8601 | 開始時刻 |
meeting_end | ISO 8601? | 終了時刻(進行中の場合は null) |
meeting_app | 文字列 | アプリ(zoom、teams、meet など) |
title | string? | ミーティングのタイトル |
attendees | string? | 参加者 |
note | string? | ユーザーのメモ/追記された AI 要約 |
detection_source | string | 検出方法(app、calendar、ui など) |
生の SQL からも利用できます:SELECT * FROM meetings WHERE meeting_start > strftime('%Y-%m-%dT%H:%M:%f+00:00', 'now', '-24 hours') LIMIT 20
10. 話者 — 管理と再割り当て
# Search speakers by name
curl -H "Authorization: Bearer $SCREENPIPE_LOCAL_API_KEY" "http://localhost:3030/speakers/search?name=John"
# Get unnamed speakers (for labeling)
curl -H "Authorization: Bearer $SCREENPIPE_LOCAL_API_KEY" "http://localhost:3030/speakers/unnamed?limit=20&offset=0"
# Get speakers similar to a given speaker (by voice embedding)
curl -H "Authorization: Bearer $SCREENPIPE_LOCAL_API_KEY" "http://localhost:3030/speakers/similar?speaker_id=29&limit=5"
# Update speaker name/metadata
curl -X POST http://localhost:3030/speakers/update \
-H "Content-Type: application/json" \
-d '{"id": 29, "name": "Jordan"}'
# Reassign speaker for an audio chunk (propagates to similar chunks by default)
curl -X POST http://localhost:3030/speakers/reassign \
-H "Content-Type: application/json" \
-d '{"audio_chunk_id": 456, "new_speaker_name": "Jordan", "propagate_similar": true}'
# Returns: new_speaker_id, transcriptions_updated, old_assignments (for undo)
# Undo a speaker reassignment
curl -X POST http://localhost:3030/speakers/undo-reassign \
-H "Content-Type: application/json" \
-d '{"old_assignments": [{"transcription_id": 1, "old_speaker_id": 29}]}'
# Merge two speakers (keeps one, merges the other into it)
curl -X POST http://localhost:3030/speakers/merge \
-H "Content-Type: application/json" \
-d '{"speaker_to_keep_id": 5, "speaker_to_merge_id": 29}'
# Mark speaker as hallucination (false detection)
curl -X POST http://localhost:3030/speakers/hallucination \
-H "Content-Type: application/json" \
-d '{"speaker_id": 29}'
# Delete a speaker (also removes associated audio chunk files)
curl -X POST http://localhost:3030/speakers/delete \
-H "Content-Type: application/json" \
-d '{"id": 29}'
話者の再割り当てワークフロー
ユーザーが「それはKarishmaではなく、実際にはJordanでした」と言った場合:
- 音声の検索結果から、誤って識別された音声の
chunk_idを見つけます audio_chunk_idとnew_speaker_nameを指定してPOST /speakers/reassignを呼び出しますpropagate_similar: true(デフォルト)にすると、似た音声のチャンクも修正されます
11. 解析済みアプリデータとアクター
解析済みデータは、他のすべての読み取り可能なコンテンツタイプと同じ検索インターフェイスを使用します。
curl -H "Authorization: Bearer $SCREENPIPE_LOCAL_API_KEY" \
"http://localhost:3030/search?content_type=parsed&start_time=2h%20ago&limit=10"
結果には、修正済みのコンパクトな text、型付きの items、パーサーの来歴情報、および修正可能な ID を格納した別個の actors 配列が含まれます。frame_id でフレームを 1 つに絞り込むか、actor_id で解決済み ID を 1 つに絞り込めます。アクターの編集は明示的に行います。まず GET /semantic/actors/search を実行し、次に POST /semantic/actors/create、update、merge、reassign、または aliases/reassign を呼び出します。表示名だけを根拠にアクターを統合しないでください。パーサーのラベルは観測された証拠であり、アクターのレコードは変更可能です。
12. メモリー — 価値の高い永続的な知識
メモリーは、screenpipe で最も価値の高いデータソースです。 画面や音声のデータを何時間分も整理して抽出した、厳選された事実、ユーザーの好み、決定事項、プロジェクトのコンテキストが含まれています。質問に回答するときやコンテキストを構築するときは、必ずメモリーを確認してください。
メモリーを検索するタイミング
次の場合は、**まずメモリーを検索してから(または /search と並行して)**ください。
- ユーザーが好み、決定事項、または過去のコンテキストについて尋ねている
- プロジェクト、人物、ワークフローについて背景情報が必要
- 要約、推奨事項、アクションプランを作成している
- ユーザーの好みや過去の決定事項が不明
- 過去のコンテキストによって出力が改善されるあらゆるタスク
ルール:/search を呼び出す場合は、並行して /memories も呼び出してください。 メモリーは、生の画面データの背景にある「理由」を示します。検索で分かるのは何が起きたかであり、メモリーでは何が重要かが分かります。
API
# Search memories (FTS) — do this often!
curl -H "Authorization: Bearer $SCREENPIPE_LOCAL_API_KEY" "http://localhost:3030/memories?q=preference&limit=20"
# List recent memories (high importance first)
curl -H "Authorization: Bearer $SCREENPIPE_LOCAL_API_KEY" "http://localhost:3030/memories?min_importance=0.5&limit=20"
# Filter by source or tags
curl -H "Authorization: Bearer $SCREENPIPE_LOCAL_API_KEY" "http://localhost:3030/memories?source=user&tags=project&limit=20"
# Create a memory
curl -X POST http://localhost:3030/memories \
-H "Content-Type: application/json" \
-d '{"content": "User prefers dark mode", "source": "user", "tags": ["preference", "ui"], "importance": 0.7}'
# Update a memory
curl -X PUT http://localhost:3030/memories/1 \
-H "Content-Type: application/json" \
-d '{"content": "User prefers dark mode in all apps", "importance": 0.8}'
# Delete a memory
curl -X DELETE http://localhost:3030/memories/1
GET /memories のパラメーター:q(FTS 検索)、source、tags、min_importance、start_time、end_time、limit、offset。
メモリは /search?content_type=memory にも表示されます。
メモリの作成
ユーザーについて重要なこと(好み、決定事項、プロジェクトのコンテキスト)を学んだら、メモリとして保存します。シグナルの重要度を順位付けするには、importance に 0.0〜1.0 を設定します。一時的な観察ではなく、本当に役立つ長期的な事実だけを保存してください。
12. 通知 — POST http://localhost:11435/notify
screenpipe のデスクトップ UI に通知を送信します。これは Tauri サイドカーサーバー(ポート 11435)を使用し、メイン API(ポート 3030)は使用しません。
通知本文ではマークダウン(**太字**、`インラインコード`、[リンクテキスト](url))を使用できます。リンクには、Web URL、ファイルパス、screenpipe のディープリンクを指定できます。
priority には high、normal(デフォルト)、または low を設定します。どの優先度の通知も右上の通知パネルに表示されます。high は、時間的制約のある障害や、人間が今すぐ対応する必要がある重要な判断のためにのみ使用してください。high は、フォーカスされた Priority 受信トレイにも表示されます。normal は All に表示され、low はデフォルトでトーストのみ表示されます。完了ログや定期的な同期を high にしてはいけません。
# Simple notification
curl -X POST http://localhost:11435/notify \
-H "Content-Type: application/json" \
-d '{"title": "3 new voice memos", "body": "found recordings from today"}'
# Markdown body with links
curl -X POST http://localhost:11435/notify \
-H "Content-Type: application/json" \
-d '{"title": "Meeting summary", "body": "**Q3 Planning** notes saved\n\nopen [meeting notes](~/Documents/notes/q3.md) or view [recording](screenpipe://timeline)"}'
# Link to a local file (absolute path or ~ path)
curl -X POST http://localhost:11435/notify \
-H "Content-Type: application/json" \
-d '{"title": "Export complete", "body": "saved to [report.csv](~/Downloads/report.csv)"}'
# With action buttons
# Use `type: "link"` for external URLs and `type: "deeplink"` for
# screenpipe:// in-app routes. `type: "dismiss"` closes the notification.
curl -X POST http://localhost:11435/notify \
-H "Content-Type: application/json" \
-d '{"title": "Meeting summary", "body": "**Q3 Planning**\n- Budget approved", "actions": [{"id": "view", "label": "view", "type": "deeplink", "url": "screenpipe://timeline"}, {"id": "skip", "label": "skip", "type": "dismiss"}]}'
# External URL action (opens in browser)
curl -X POST http://localhost:11435/notify \
-H "Content-Type: application/json" \
-d '{"title": "PR ready for review", "body": "nice work", "actions": [{"id": "open", "label": "open pr", "type": "link", "url": "https://github.com/screenpipe/screenpipe/pull/1234"}]}'
# Ask permission, then run a pipe on approval — the opt-in / agent-gated flow.
# `type: "pipe"` runs the TARGET pipe when clicked (POST /pipes/<pipe>/run); the
# `context` is injected into that pipe's prompt as the notification action
# context. Set `pipe` EXPLICITLY — if omitted it falls back to the sending pipe,
# which usually does nothing. Add `"open_in_chat": true` to run it in the chat UI
# so the user sees the output live instead of in the background.
# Actions persist into the notification bell, so the user can still approve from
# the bell after the ~20s toast fades.
curl -X POST http://localhost:11435/notify \
-H "Content-Type: application/json" \
-d '{"title": "share meeting notes with the team?", "body": "approve to send the adriaan call notes", "priority": "high", "actions": [{"id": "approve", "label": "approve", "type": "pipe", "primary": true, "pipe": "share-data", "context": {"meeting_id": 274}}, {"id": "decline", "label": "decline", "type": "dismiss"}]}'
# Run an inline prompt in a fresh chat session on click (`type: "chat"`).
# No pre-installed pipe needed — write the whole task in `prompt`, attach data
# in `context`. Add `"auto_send": false` to pre-fill chat for the user to
# review/edit before sending. This is the lightweight counterpart to a `pipe`
# action for one-off "approve → do this specific thing" flows.
curl -X POST http://localhost:11435/notify \
-H "Content-Type: application/json" \
-d '{"title": "summarize this call into a CRM note?", "body": "approve to draft it", "priority": "high", "actions": [{"id": "go", "label": "draft it", "type": "chat", "primary": true, "prompt": "summarize meeting 274 into a short CRM follow-up note and save it to output/", "context": {"meeting_id": 274}}, {"id": "no", "label": "no", "type": "dismiss"}]}'
# Call a local API endpoint on click (`type: "api"`)
curl -X POST http://localhost:11435/notify \
-H "Content-Type: application/json" \
-d '{"title": "stop recording?", "body": "tap to stop", "actions": [{"id": "stop", "label": "stop", "type": "api", "url": "/recording/stop", "method": "POST"}]}'
# Custom auto-dismiss (5 seconds)
curl -X POST http://localhost:11435/notify \
-H "Content-Type: application/json" \
-d '{"title": "Saved", "body": "Note saved", "timeout": 5000}'
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
title | 文字列 | はい | 通知タイトル |
body | 文字列 | はい | マークダウン本文(**太字**、`コード`、[テキスト](url)) |
type | 文字列 | いいえ | カテゴリー(デフォルトは "pipe") |
priority | high | normal | low | いいえ | デフォルトは normal。すべての優先度が右上に表示され、フォーカスされた Priority ビューに入るのは high のみです |
timeout | 整数 | いいえ | ミリ秒単位の自動非表示時間(デフォルトは 20000) |
autoDismissMs | 整数 | いいえ | timeout の別名 |
actions | 配列 | いいえ | アクションボタン(最大 5 個。それぞれに id、label、type が必要です) |
アクションボタンの type:
link— ブラウザーで Web URL を開きます(url)deeplink— screenpipe 内を移動します(url=screenpipe://...)pipe— クリック時にインストール済みの pipe を実行します(pipe= 対象の pipe 名、任意のcontextをプロンプトに挿入、任意のopen_in_chat)。オプトイン/エージェントによる共有制御の仕組みです。chat— 新しいチャットセッションでインラインのpromptを実行します(インストール済みの pipe は不要。任意のcontextを背景データとして指定でき、auto_sendは任意で、デフォルトは true)。単発の「承認して実行」フローに適した、pipeに相当する軽量な機能です。api— ローカルエンドポイントに POST します(url、任意のmethod、任意のbody)dismiss— 通知を閉じます。副作用はありません。primary: trueを指定すると、ボタンが塗りつぶしで表示されます(推奨アクション)。アクションは通知ベルに保持されるため、トーストを見逃しても後から操作できます。
本文のマークダウンでサポートされるリンクの種類:
- Web URL:
[docs](https://docs.screenpi.pe)— ブラウザーで開きます - ファイルパス:
[notes](~/notes/file.md)または[log](/var/log/app.log)— デフォルトのアプリで開きます - ディープリンク:
[timeline](screenpipe://timeline)— screenpipe 内を移動します
{"success": true, "message": "Notification sent successfully"} を返します。
13. その他のエンドポイント
curl http://localhost:3030/health # Health check
curl http://localhost:3030/audio/list # Audio devices
curl http://localhost:3030/vision/list # Monitors
ディープリンク
クリック可能なリンクで特定の時点を参照します:
[10:30 AM — Chrome](screenpipe://frame/12345) # screen text results (use frame_id)
[meeting at 3pm](screenpipe://timeline?timestamp=ISO8601) # Audio results (use timestamp)
実際の検索結果に含まれる ID/タイムスタンプのみを使用してください。捏造してはいけません。
動画の表示
再生可能な動画をインラインコードで表示するには、検索結果の file_path を指定します:
`/Users/name/.screenpipe/data/monitor_1_2024-01-15_10-30-00.mp4`