mcpField
S
screenpipe-api

screenpipe-api

github.com/screenpipe生产力22.1k40 次安装今天更新
代码仓库

关于 screenpipe-api

Screenpipe 本地 REST API 的使用指南,面向需要检索屏幕、音频和活动记录的 Agent 或脚本,涵盖搜索、活动摘要、标签、同步设备查询及响应大小控制。

主要功能

  1. 01搜索屏幕、音频和解析数据
  2. 02汇总时间范围内的活动
  3. 03用标签关联捕获记录与记忆
  4. 04查询同步设备
  5. 05通过格式和字段缩减响应

适用场景

  1. 01查找指定时间段的屏幕或音频记录
  2. 02回顾不同应用和窗口的活动
  3. 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 层。切勿在此标头中填写 Agent 名称、客户名称、项目、提示词或其他动态值。 对 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),还可以在源头减少 token:添加 &format=csv(或 tsv),即可获取按列排列的表格,每个列名只写一次,而不是每行重复键;添加 &fields=a,b,c 可仅返回所需列(支持 content.text 这类点号路径)。对于 UI 元素列表,相较于 JSON,这种方式大约可减少 70% 的 token。对于元素端点,&format=outline(别名 tree)还能进一步精简——它会生成去重、缩进的树形结构,仅包含带文本的节点(经测量,token 减少约 91%),是读取 UI 结构的最佳默认格式。规划自动化时使用 &format=automation:它会保留交互控件、状态、边界、允许的操作、响应内短引用以及尽力提取的稳定键。文本密集的 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字符串否关键词。音频搜索时请勿使用——转录内容噪声较多,q 会过度筛选。
content_type字符串否all(默认)、accessibility、audio、input、ocr、memory、parsed。对于简洁的应用专属消息、电子邮件、任务、文档和代码审查,请使用 parsed。解析捕获功能尚处于实验阶段,在禁用或不受支持时可能为空,且不包含在 all 中。屏幕文本主要通过操作系统的辅助功能树(accessibility)捕获;对于不支持辅助功能的应用,OCR 是备用方案。
limit整数否最大值为 1-20。默认值:10
offset整数否分页。默认值:0
start_timeISO 8601、相对时间或本地日历日期是可接受 2024-01-15T10:00:00Z、16h ago、today、yesterday 或 YYYY-MM-DD
end_time与 start_time 相同否默认为 now
app_name字符串否例如 "Google Chrome"、"Slack"、"zoom.us"
window_name字符串否窗口标题子字符串
frame_id整数否当 content_type=parsed 时,返回附加到某一帧的解析数据。
actor_id整数否当 content_type=parsed 时,按已解析的参与者身份筛选。
speaker_name字符串否按说话者筛选音频(不区分大小写的部分匹配)
focused布尔值否仅限聚焦窗口
tags字符串否以逗号分隔;仅返回包含所有这些标签的项目(例如 person:ada,project:atlas)。适用于屏幕/音频,以及 content_type=memory 时的记忆。请参阅下文的标签。
include_related布尔值否与 tags 搭配使用时,还会返回 related 映射,其中列出共同出现的标签(与你的标签同时出现的人物/项目/工作流),并按频率从高到低排列。一次调用即可获取周边上下文,无需多次调用。请参阅下文的标签。
max_content_length整数否截断每条结果的文本(从中间截断)
format字符串否json(默认)、csv、tsv/table 或 outline/tree(仅限元素端点)。CSV/TSV 会返回列表格式的表格(列名只写一次),而不是每行一个 JSON 对象。outline 会返回去重后的缩进文本树,其中包含带文本的 UI 节点——对于“屏幕上有什么?”这类问题,这是成本最低的读取方式(token 数约减少 91%)。CSV 不会丢失数据;TSV 会合并换行符(处理较长的 ocr 文本时效果较差)。
fields字符串否以逗号分隔的列白名单,使用点分隔路径,例如 type,content.app_name,content.text。仅返回这些列(便于移除重复的绝对路径 content.file_path)。json 格式也适用(返回稀疏对象)。
渐进式信息披露

不要直接调用开销较大的 /search。请逐步升级:

步骤端点适用场景
0GET /memories?q=...始终优先查询/并行查询——信号最强、成本最低
1GET /activity-summary?start_time=...&end_time=...宽泛的问题(“我在做什么?”、“用了哪些应用?”)
2GET /search?...需要查找具体内容
3GET /elements?... 或 GET /frames/{id}/contextUI 结构、按钮、链接
4GET /frames/{frame_id} (PNG)需要视觉上下文

决策树:

  • “我在做什么?” → 仅步骤 1
  • “总结一下我的会议” → 步骤 2,使用 content_type=audio,不要使用 q 参数。添加 content_type=all 以获取屏幕上下文。
  • “在 X 上花了多长时间?” → 步骤 1(/activity-summary → 整个时间范围的 total_active_minutes,以及每个应用/窗口的 minutes)
  • “今天用了哪些应用?” → 步骤 1(不要使用帧计数或原始 SQLite)
  • “我点击了哪个按钮?” → 步骤 3(/elements,role=AXButton)
  • “展示我看到的内容” → 步骤 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。带有相同标签的两个项目会关联起来。

  • 添加到画面/音频: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)。

在标签查询中添加 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 计算午夜,也不要附加 T00:00:00Z。

  1. 始终包含 start_time — 不带时间范围的查询会超时
  2. 从 1–2 小时的范围开始 — 仅在没有结果时扩大范围
  3. 用户提到特定应用时,使用 app_name
  4. 初始时将 limit 设得较低(5–10)
  5. “recent” = 30 分钟
  6. 如果超时,请缩小时间范围
响应格式
{
  "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" 类型标签用于所有屏幕文本结果,包括通过辅助功能树捕获的文本。


已同步设备 — 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 会提供已登录的身份信息。


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:每个窗口上下文的一段代表性文本片段(优先显示用户输入字段,而非静态页面文本)
  • audio_summary.top_transcriptions:实际转录文本,含说话者和时间戳(不只是计数)

通常只需这些信息,就足以回答“我当时在做什么?”,无需进一步搜索。只有在需要逐字引述或特定内容时,才深入查询 /search。

在构建管道/自动化流程? 规则相同:请调用此端点进行时间计算。数值由服务端根据帧时间戳计算——切勿根据原始帧重新计算时长,也不要让大模型累加分钟数(结果会产生偏差)。让模型为活动添加标签;时长则交由此端点处理。


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 是引用标识,内联显示 (disabled)/(selected)/(focused)/(expanded)/(off-screen) 状态,并限制正文长度)。最适合 source=accessibility(常见的 UI 场景——包含结构噪声、重复行、层级和状态):与 JSON 相比,可减少 85–99% 的 token(o200k_base)。扁平的 OCR 文本块压缩空间较小(约 67%,没有可去重的内容)——对于纯 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"
常见角色(因平台而异)

各平台的角色未经过标准化。请根据用户的操作系统使用正确格式:

概念macOSWindowsLinux
按钮AXButtonButtonButton
静态文本AXStaticTextTextLabel
链接AXLinkHyperlinkLink
文本字段AXTextFieldEditEntry
文本区域AXTextAreaDocumentText
菜单项AXMenuItemMenuItemMenuItem
复选框AXCheckBoxCheckBoxCheckBox
组AXGroupGroupGroup
Web 区域AXWebAreaPaneDocumentWeb
标题AXHeadingHeaderHeading
标签页AXTabTabItemTab
列表项AXRowListItemListItem

仅 OCR 角色(无障碍功能不可用时的回退选项):line、word、block、paragraph、page


4. 帧(屏幕截图)— GET /frames/{frame_id}

curl -o /tmp/frame.png "http://localhost:3030/frames/12345"

返回原始 PNG。每次查询最多获取 2–3 帧(每帧约 1000–2000 个 token)。


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。始终按时间筛选。仅限只读。时间计算请参阅下文的时间戳注意事项。

时间戳注意事项:数据库时间戳以 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 查询屏幕使用时间。

架构
表关键列时间列
framesapp_name、window_name、browser_url、focusedtimestamp
ocr_texttext、app_name、window_name通过 frame_id 联结
elementssource、role、text、bounds_*通过 frame_id 联结
audio_transcriptionstranscription、device、speaker_id、is_input_devicetimestamp
audio_chunksfile_pathtimestamp
speakersname、metadata—
ui_eventsevent_type、app_name、window_title、browser_urltimestamp
accessibilityapp_name、window_name、text_content、browser_urltimestamp
meetingsmeeting_app、title、attendees、detection_sourcemeeting_start
memoriescontent、source、tags、importancecreated_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 是针对标题、参会者和备注的不区分大小写的子串筛选条件。

会议更新使用 PUT /meetings/:id,而非 PATCH。在追加 AI 生成的摘要之前,请先读取当前会议,并将现有的 note 文本包含在新备注正文中,以保留用户编写的备注。

字段类型描述
idinteger会议 ID
meeting_startISO 8601开始时间
meeting_endISO 8601?结束时间(进行中时为 null)
meeting_appstring应用(zoom、teams、meet 等)
titlestring?会议标题
attendeesstring?参会者
notestring?用户备注 / 追加的 AI 摘要
detection_sourcestring检测方式(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}'
说话人重新分配工作流

当用户说“那其实是 Jordan,不是 Karishma”时:

  1. 搜索音频结果,找到被错误识别音频的 chunk_id
  2. 调用 POST /speakers/reassign,并传入 audio_chunk_id 和 new_speaker_name
  3. 设置 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、解析器来源信息,以及单独的 actors 数组,用于可更正的身份信息。使用 frame_id 筛选单个帧,或使用 actor_id 筛选单个已解析身份。参与者编辑需明确执行:先调用 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(全文搜索)、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 sidecar 服务(端口 11435),而不是主 API(端口 3030)。

通知正文支持 markdown:**粗体**、`行内代码` 和 [链接文本](url)。链接可以是网页 URL、文件路径或 screenpipe 深层链接。

将 priority 设为 high、normal(默认值)或 low。每种优先级的通知都会显示在右上角的通知面板中。只有在需要立即告知用户的时效性故障或重要决策时才使用 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}'
字段类型必填说明
titlestring是通知标题
bodystring是Markdown 正文(**粗体**、`代码`、[文本](url))
typestring否类别(默认值为 "pipe")
priorityhigh | normal | low否默认值为 normal;所有优先级的通知都会显示在右上角,只有 high 会进入专门的 Priority 视图
timeoutinteger否自动关闭时间,单位为毫秒(默认值为 20000)
autoDismissMsinteger否timeout 的别名
actionsarray否操作按钮(最多 5 个;每个按钮都需要 id、label、type)

操作按钮的 type:

  • link — 在浏览器中打开网页 URL(url)
  • deeplink — 在 screenpipe 中导航(url = screenpipe://...)
  • pipe — 点击时运行已安装的 pipe(pipe = 目标 pipe 名称,可选的 context 会注入其提示词,可选的 open_in_chat)。用于选择加入或由 Agent 控制分享的机制。
  • chat — 在新的聊天会话中运行内联 prompt(无需安装 pipe;可选的 context 作为背景数据,可选的 auto_send 默认值为 true)。这是 pipe 的轻量替代方式,适用于一次性的“批准并执行”流程。
  • api — 向本地端点发送 POST 请求(url,可选的 method、body)
  • dismiss — 关闭通知,不产生其他副作用
  • primary: true 会以填充样式显示按钮(推荐操作)。操作会保留在通知铃铛中,因此即使错过了短暂通知,仍然可以执行操作。

正文 Markdown 支持的链接类型:

  • 网页 URL:[文档](https://docs.screenpi.pe) — 在浏览器中打开
  • 文件路径:[笔记](~/notes/file.md) 或 [日志](/var/log/app.log) — 在默认应用中打开
  • 深层链接:[时间线](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`

评论

支持 Markdown