npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@streamapp/stream

v0.0.16

Published

Stream — a self-hostable information-flow layer: many sources into one inbox, exposed to AI over MCP

Downloads

2,204

Readme

Stream

把很多信息源(RSS / RSSHub 路由 / 小红书、B站、抖音这类站点 / 网盘 / 播客)汇进一个收件箱, 并把整个收件箱开放给 AI(MCP)的自托管信息流层。所有数据都在你自己机器上。

npx @streamapp/stream                    # 试一下
npm i -g @streamapp/stream && stream     # 长期用

需要 Node 20+node -v 查;没有就去 https://nodejs.org 装 LTS,Windows 上 winget install OpenJS.NodeJS.LTS 也行)。除了 Node 别的什么都不用装——不需要 git、不需要 Docker、不需要 Python 或编译器(原生依赖有预编译包)。 开箱这一次是 96 个包 / 230MB / 十几秒。

装完打开 http://127.0.0.1:8900

stream [--port <n>] [--data <dir>]

  --port, -p <n>   监听端口(默认 8900)
  --data <dir>     数据目录(默认 ~/.stream)
  • 数据全在 ~/.stream:删掉它就是重置;卸载 = 删掉它 + npm rm -g @streamapp/stream
  • 只有一个端口:前端、/api/*/ws、插件全走 8900 这一扇门。
  • 大件用到才装,不占开箱体积:RSSHub 在第一次跑到 RSSHub 源时装(约 400MB,43~147 秒, 看机器和网络)。

上手:五步,每步都有判据

下面每一步都给了一条能跑的命令和一个该看到的答案。判据不过就别往下走——这条链路上每一种 坏法都是安静的(采到游客态数据、流不排班、能力显示可用但一跑就失败),往下走只会把一个静默的 失败带到更远的地方。

1. 把 Chrome 扩展装上 —— 不装的后果是静默的

采集借你自己浏览器的登录态(Stream 不自带浏览器,也不碰你的密码)。没有扩展,小红书 / B 站 / 抖音这类站点只能拿到游客看得见的东西——不报错,只是采得少、采得浅

打开 http://127.0.0.1:8900 首次会引导你装。手动装:

curl -s -X POST 127.0.0.1:8900/api/extension/materialize    # → {"dir":"…/.stream/extension"}

拿那个 dir 去 Chrome:chrome://extensions → 打开右上角开发者模式加载已解压的扩展程序 → 选那个目录。(Chrome 从 137 起移除了 --load-extension,命令行装不了,GUI 是唯一的路。)

扩展连后端之前要经一个本机小程序(host agent)拿一把钥匙。后端启动时自己把它登记进 Chrome 并拉起, 不用你装别的;启动日志里有一行 [stream-computer-use] host-agent → <路径> 就是登记成功。今天这个小程序只有 Windows 版(mac / Linux 上后端会记一行 warn,扩展配不上,采集只有游客态)。

判据(唯一可信的那个,别看 Chrome 里的图标):

curl -s 127.0.0.1:8900/api/browser-capability     # → {"state":"ready","connected":true,…}
  • "never-seen" = 从没连上过 → 还没装,或者装在了另一个 Chrome 上。
  • "disconnected" = 装过、现在没连 → 点一下扩展图标叫醒它(Chrome 会让它休眠,后端重启后尤其)。

2. 订第一条流 —— 记得给它一个频道

先找源:

curl -s -G 127.0.0.1:8900/api/sources --data-urlencode "q=播客"

members[].source 填它回的 id真正必须对的是这一个),plugin 填它的 adapterrsshub / replay / builtin …):

curl -s -X POST 127.0.0.1:8900/api/streams -H 'content-type: application/json' -d '{
  "id": "my-podcast",
  "label": "故事FM",
  "strategy": "fanout",
  "cadence_seconds": 86400,
  "options": {},
  "channel_id": "default-audio",
  "members": [{ "plugin": "replay", "source": "@streamapp/lizhi/lizhi-user",
                "params": { "id": "2657184879512415276" } }]
}'

channel_id 不是可选的讲究:一条不属于任何频道的流,这次会话在调度里、重启之后就没了 (开机只装载被某个频道引用的流)。要绑就在建流这一句里绑,别建完再补。频道用 curl -s 127.0.0.1:8900/api/channels 看,开箱自带四个(default-timeline / default-audio / default-video / default-tasks)。

判据

curl -s -X POST 127.0.0.1:8900/api/streams/my-podcast/refresh   # → {"fetched":961,"written":961}

fetched: 0 不是"没有新内容"。常见成因:那个 source 在本机解析不到、参数不对、缺登录态、 或者那条源坏了。去 curl -s "127.0.0.1:8900/api/debug/log?channel=harvest" 看这一轮的分阶段 结论——日志里连一条这个源的记录都没有,就是根本没跑到它,而不是跑了没结果。

3. 打开需要钥匙的能力(转写 / 认字 / 摘要)

先问它现在缺什么:

curl -s 127.0.0.1:8900/api/conversion-kinds
# extract 那一行的 branches: {"stt":false,"ocr":true,"article":true}   ← stt 缺钥匙

要语音转文字就配一把 Groq 的 key。Stream 可以替你去申请——它在你自己的 Chrome 里打开厂商 控制台、用你已经登录的账号建一把新 key,写进本地配置(不经过任何第三方)。

前提:先在那个 Chrome 里登录 https://console.groq.com(Groq 支持用 Google 账号登录,免费额度 够用)。这一步用的就是你现成的登录态——没登录的话它会停在登录页,这不是失败,是缺前提。

curl -s -X POST 127.0.0.1:8900/api/source-runtime-config/provision \
  -H 'content-type: application/json' \
  -d '{"pluginId":"builtin","sourceId":"groq-whisper","params":{"name":"stream-auto-7f3a"}}'
# → secrets.apiKey.configured: true            实测约 17 秒

自己去 https://console.groq.com/keys 拿一把、用 PUT /api/source-runtime-config 填进去也行。 配完不用重启,下一次问就变了:

curl -s 127.0.0.1:8900/api/conversion-kinds     # branches.stt → true

转写一集:

curl -s -X POST 127.0.0.1:8900/api/conversions -H 'content-type: application/json' \
     -d '{"kind":"extract","item":"<item id>"}'      # → {"id":"cv_…","status":"running"}
curl -s 127.0.0.1:8900/api/conversions/cv_…          # 轮到 status:"done",result.text 就是文字稿

一小时的播客约 4~5 分钟(取媒体和重编码占大头,真正的识别只要几十秒)。

4. 接一个对话宿主(可选)

Stream 自己没有对话,用你已有的 agent。三步,第三步才是可选的:

一、装 Stream。 第 1 步已经做完了(npm i -g @streamapp/stream && stream)。 装了它就有电脑操作——用户自己那个已登录的 Chrome,加上原生桌面窗口。

二、宿主那边配一行,指向 Stream。

claude mcp add stream -- stream mcp      # Codex 是 config.toml 的 mcp_servers 一行

stream mcp 是一层 stdio 壳:它探一次本机的后端,在场就整面转发到 /api/mcp,不在场就先把 后端拉起来再转发。这一行此后不用再改——往 Stream 里加多少能力,工具都从同一个口出去。

三、想要更多能力就往里加:

stream add @streamapp/netdisk      # 网盘:验分享 / 转存 / 直链 / 跳转
stream add @streamapp/meituan      # 美团:领券 / 到店团购搜索 / 下单
stream remove @streamapp/netdisk   # 不想要了

能力包是 Stream 包的一格槽位(package.json#stream.capability),装进 <dataDir>/recipes/ 后由后端在自己进程里挂上——登录态不出这个进程。界面上的「组件」页里点装是同一条路。 装完要重启后端才生效(安装那一刻只落盘),装上了没有的话先重启再排查。

再往下:第 5 节把 Stream 的 skill 装给你的 agent(MCP 给工具,skill 给"什么时候用哪个")。

DSH 用户多一样:Stream UI bundle

DSH 装上它之后整张脸就是 Stream(内容流 + 对话)。它也读第 5 节装的那批 skill(同一个 ~/.agents/skills/ 目录):

npm i -g @deepseek-ai/[email protected]   # 引擎版本要对得上:这份 bundle 按 0.1.2 的客户端模块表构建
# 装进已经带 web 界面的那个 profile($DSH_HOME/profiles/web)——bundle 关掉的是 web-app 的整页壳,
# 新建的空 profile 里没有它可关。想单独留一个 profile 给 Stream:先 cp -r profiles/web profiles/stream,再把下面的 web 换成 stream。
dsh plugin --profile web add @streamapp/dsh-plugin-stream-ui
dsh web                                                          # 单独的 profile 就是 dsh --profile stream

这份 bundle 是唯一要装进 DSH profile 的东西;能力包一律装进 Stream,DSH 那边一个字都不用改。 Stream 后端照常跑着就行(stream),那张页在本机哪个口上都不用告诉它——本机来源默认可信。 后端和 DSH 不在同一台机器时才需要登记:STREAM_TRUSTED_ORIGINS=http://<那台机器>:<口> stream

模型是你自己的:在 DSH 的「设置 - 模型」页配 provider;Stream 不参与。 前面三步都不依赖它——收集、采集、转写都不用模型。

接给别的 AI 客户端(MCP)

不走 stream mcp 也行:后端跑着就直接用 HTTP 这一档 http://127.0.0.1:8900/api/mcp (设了 api_token 才需要 Authorization: Bearer …)。不想让后端常驻就用 stdio 那一档, 客户端按需拉起进程。三条路的工具集一样。

5. 把 Stream 的 skill 装进你自己的 agent(Claude Code / Codex)

上一步给的是工具,这一步给的是手艺——什么时候用哪个、按什么顺序、什么算数。

curl -s -X POST 127.0.0.1:8900/api/skills/install

它把随包出货的 skill 刷进 ~/.stream/skills/,再从 ~/.claude/skills/(Claude Code)和 ~/.agents/skills/(Codex)链接过去。是链接不是拷贝——升级之后两边同时变新。

判据

curl -s 127.0.0.1:8900/api/skills      # hosts[].landings[].mode 都是 "link"

Claude Code 里敲 /stream- 看得到它们,Codex 里是 $stream-。名字一律带 stream- 前缀, 不会顶掉你自己的同名 skill;那个位置已经有别的东西就跳过并说明。撤销用 POST /api/skills/uninstall(只删它自己建的那些)。mode"copy" 说明这台机器建不出 符号链接——功能一样,但升级后要再跑一次 install。


出问题时先跑这几句

以副作用为准,不要以"应该好了"为准——每一种坏法都是安静的。

| 问 | 命令 | 绿的样子 | |---|---|---| | 后端活着吗 | curl -s 127.0.0.1:8900/api/health | {"ok":true} | | 采集的手在不在 | curl -s 127.0.0.1:8900/api/browser-capability | "state":"ready" | | 这条流在调度里吗 | curl -s 127.0.0.1:8900/api/streams | 看得到你建的那个 id | | 它真采到东西了吗 | POST /api/streams/<id>/refresh | fetched > 0 written > 0 | | 这个能力现在能用吗 | curl -s 127.0.0.1:8900/api/conversion-kinds | 那条的 available / branches.* 为 true | | 我自己写的 recipe 装载了吗 | curl -s 127.0.0.1:8900/api/recipes/local | ok: truedir 就是该往哪写;没装载会带 error 原文) |

三个最容易误判的地方:

  • fetched: 0 不等于「没有新内容」(见第 2 步)。
  • 建流不带 channel_id:这次能跑,重启后消失。
  • 「配好了」不等于「能用了」:判据是那条能力自己的自述(/api/conversion-kinds), 不是配置那一格的 configured

MIT · 数据全在本机,不上传任何地方。