stream-flutter

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Stream Flutter - skill router + execution flow

Stream Flutter - 技能路由与执行流程

Rules: Read
RULES.md
once per session - every non-negotiable rule is stated there, nowhere else.
This file is the single entrypoint: intent classification, local project detection, and module pointers for Stream work in Flutter apps.

规则: 每次会话需阅读一次
RULES.md
—— 所有不可协商的规则均在此文件中,无其他位置说明。
本文件是唯一入口:用于Flutter应用中Stream相关工作的意图分类、本地项目检测以及模块指引。

Step 0: Intent classifier (mandatory first - never skip)

步骤0:意图分类器(必须首先执行 - 切勿跳过)

Before any tool call, decide the track from the user's input alone - no probes first.
在调用任何工具之前,仅根据用户输入决定跟踪路径 —— 无需先进行探查。

Signals -> track

信号 → 跟踪路径

Signal in user inputTrack
Explicit package/widget token:
stream_chat_flutter
,
StreamChannelListView
,
StreamMessageListView
,
StreamChatClient
, etc.
C - Reference lookup
Explicit video token:
stream_video_flutter
,
StreamCallContainer
,
StreamVideo
,
StreamVideoRenderer
,
goLive
,
stopLive
,
livestream
call type
C - Reference lookup
Explicit feeds token:
stream_feed
,
stream_feed_flutter_core
,
StreamFeedClient
,
FlatFeedCore
,
FlatFeed
,
FeedBloc
,
activity feed
,
feeds flutter
C - Reference lookup
Words "docs" or "documentation" around Stream Flutter workC - Reference lookup
"How do I {X} in Flutter?", "What does {widget/method} do?"C - Reference lookup
"Build me a new Flutter app", "create a Flutter chat app" + StreamA - New app
"Build a Flutter video call app", "create a livestream app in Flutter"A - New app (load
VIDEO-FLUTTER.md
+
VIDEO-FLUTTER-blueprints.md
or
LIVESTREAM-FLUTTER.md
+
LIVESTREAM-FLUTTER-blueprints.md
)
"Build an audio room / Twitter Spaces clone", "TikTok-style live feed", "call while livestreaming", "chat with video calls", "two calls at once"A or B (load
VIDEO-ADVANCED-FLUTTER.md
+
VIDEO-ADVANCED-FLUTTER-blueprints.md
on top of the Video/Livestream pair)
"Add ringing / incoming calls", "video call with push notifications", "CallKit", "VoIP push", "FCM ringing", "missed call notification"A or B (load
RINGING-FLUTTER.md
+
RINGING-FLUTTER-blueprints.md
on top of the Video pair)
"Build a Flutter feeds app", "create an activity feed app", "build a social feed in Flutter", "create a Twitter/Instagram clone"A - New app (load
FEEDS-FLUTTER.md
+
FEEDS-FLUTTER-blueprints.md
; use Twitter-style UI unless the user explicitly specifies otherwise)
"Add/integrate Stream into this app", "wire Chat into my Flutter project"B - Existing app
"Add video calling to my Flutter app", "integrate Stream Video into my existing app"B - Existing app (load
VIDEO-FLUTTER.md
+
VIDEO-FLUTTER-blueprints.md
)
"Add a feed to my Flutter app", "integrate Stream Feeds into my existing app", "add activity feed"B - Existing app (load
FEEDS-FLUTTER.md
+
FEEDS-FLUTTER-blueprints.md
; use Twitter-style UI unless the user explicitly specifies otherwise)
"Install Stream packages", "set up Stream in Flutter", "wire auth/token" with no broader feature requestD - Bootstrap / setup
"Migrate my Flutter app from Sendbird", "replace
sendbird_chat_sdk
/
sendbird_uikit
with Stream", "switch off Sendbird / SendbirdUIKit"
M - Migrate from Sendbird (
sendbird-migration.md
)
Bare
/stream-flutter
with no args
List the tracks briefly and wait
用户输入中的信号跟踪路径
明确的包/组件标识:
stream_chat_flutter
StreamChannelListView
StreamMessageListView
StreamChatClient
C - 参考查询
明确的视频标识:
stream_video_flutter
StreamCallContainer
StreamVideo
StreamVideoRenderer
goLive
stopLive
livestream
通话类型
C - 参考查询
明确的信息流标识:
stream_feed
stream_feed_flutter_core
StreamFeedClient
FlatFeedCore
FlatFeed
FeedBloc
activity feed
feeds flutter
C - 参考查询
Stream Flutter相关工作中出现"docs"或"documentation"(文档)字样C - 参考查询
"How do I {X} in Flutter?"(我如何在Flutter中实现{X}?)、"What does {widget/method} do?"({组件/方法}的作用是什么?)C - 参考查询
"Build me a new Flutter app"(帮我构建一个新的Flutter应用)、"create a Flutter chat app"(创建一个Flutter聊天应用)+ StreamA - 新应用
"Build a Flutter video call app"(构建一个Flutter视频通话应用)、"create a livestream app in Flutter"(在Flutter中创建一个直播应用)A - 新应用(加载
VIDEO-FLUTTER.md
+
VIDEO-FLUTTER-blueprints.md
LIVESTREAM-FLUTTER.md
+
LIVESTREAM-FLUTTER-blueprints.md
"Build an audio room / Twitter Spaces clone"(构建音频房间/Twitter Spaces克隆版)、"TikTok-style live feed"(TikTok风格直播流)、"call while livestreaming"(直播时通话)、"chat with video calls"(视频通话时聊天)、"two calls at once"(同时进行两个通话)A或B(在视频/直播相关文档基础上,加载
VIDEO-ADVANCED-FLUTTER.md
+
VIDEO-ADVANCED-FLUTTER-blueprints.md
"Add ringing / incoming calls"(添加来电响铃功能)、"video call with push notifications"(带推送通知的视频通话)、"CallKit"、"VoIP push"(VoIP推送)、"FCM ringing"(FCM响铃)、"missed call notification"(未接来电通知)A或B(在视频相关文档基础上,加载
RINGING-FLUTTER.md
+
RINGING-FLUTTER-blueprints.md
"Build a Flutter feeds app"(构建Flutter信息流应用)、"create an activity feed app"(创建活动流应用)、"build a social feed in Flutter"(在Flutter中构建社交信息流)、"create a Twitter/Instagram clone"(创建Twitter/Instagram克隆版)A - 新应用(加载
FEEDS-FLUTTER.md
+
FEEDS-FLUTTER-blueprints.md
;除非用户明确指定,否则默认使用Twitter风格UI)
"Add/integrate Stream into this app"(在此应用中添加/集成Stream)、"wire Chat into my Flutter project"(将聊天功能接入我的Flutter项目)B - 现有应用
"Add video calling to my Flutter app"(为我的Flutter应用添加视频通话功能)、"integrate Stream Video into my existing app"(将Stream Video集成到我的现有应用中)B - 现有应用(加载
VIDEO-FLUTTER.md
+
VIDEO-FLUTTER-blueprints.md
"Add a feed to my Flutter app"(为我的Flutter应用添加信息流)、"integrate Stream Feeds into my existing app"(将Stream Feeds集成到我的现有应用中)、"add activity feed"(添加活动流)B - 现有应用(加载
FEEDS-FLUTTER.md
+
FEEDS-FLUTTER-blueprints.md
;除非用户明确指定,否则默认使用Twitter风格UI)
"Install Stream packages"(安装Stream包)、"set up Stream in Flutter"(在Flutter中配置Stream)、"wire auth/token"(配置认证/令牌)且无更广泛的功能需求D - 初始化/配置
"Migrate my Flutter app from Sendbird"(将我的Flutter应用从Sendbird迁移)、"replace
sendbird_chat_sdk
/
sendbird_uikit
with Stream"(用Stream替换
sendbird_chat_sdk
/
sendbird_uikit
)、"switch off Sendbird / SendbirdUIKit"(停用Sendbird/SendbirdUIKit)
M - 从Sendbird迁移 (
sendbird-migration.md
)
仅输入
/stream-flutter
无其他参数
简要列出所有跟踪路径并等待用户进一步说明

Styling-depth flag (orthogonal to Tracks A/B/C/D)

样式深度标记(与A/B/C/D跟踪路径正交)

If the request carries a target appearance — an attached screenshot, a Figma frame, or "make it look like WhatsApp / iMessage / Telegram / Slack / <app>" — then before feature work (Track A or B), first run the strategy decision below (components vs custom):
  • Components → run
    design-matching.md
    : read its procedure half in full — everything above the
    # Reference
    divider (Steps 1–5; it may span two Reads, so page past a mid-procedure truncation) — then Grep its Reference half per region while implementing.
  • Custom (livestream / overlay / bespoke) → run
    custom-ui.md
    instead — same region-by-region rigor, different mechanism.
The rest of this section is the components case (the common one). A reference design is a checklist of regions (header, composer buttons, where the timestamp + read receipts sit, bubble shape/tail, date separators, attachments...), and most of them differ from Stream's defaults structurally, not just by color. Do not stop at the wallpaper and bubble color — that is the known failure mode. Decompose every region first (capturing its dimensions, not just colors), then route each to one of two axes:
  1. Theming
    StreamTheme
    (a
    ThemeExtension
    on
    MaterialApp.theme.extensions
    ) owns design foundations (spacing / radius / typography / colors) and all fine-grained/leaf styling including the whole message row (
    messageItemTheme
    bubble/text/attachment/metadata,
    reactionsTheme
    ,
    reactionPickerTheme
    ,
    avatarTheme
    ,
    textInputTheme
    ,
    mediaViewerTheme
    , …), while
    StreamChatThemeData
    (passed to
    StreamChat(themeData:)
    ) owns only the chat composite-widget slots (the three headers, message-list background/wallpaper, channel-list item, quoted message, thread tile, poll themes).
  2. Widget replacement — the component factory, populated via core named slots on
    StreamComponentBuilders(...)
    (~48 leaf slots:
    messageBubble
    ,
    messageText
    ,
    reactions
    ,
    reactionPicker
    ,
    mediaViewer
    ,
    jumpToUnreadButton
    ,
    textInput
    ,
    avatar
    , …) and chat slots via
    streamChatComponentBuilders(...) → extensions:
    (~30 composite slots:
    messageItem
    ,
    messageComposer
    + sub-slots,
    channelListItem
    , per-attachment builders, …), passed to
    StreamChat(componentBuilders: StreamComponentBuilders(...))
    (global) or
    StreamComponentFactory(builders: …, child: …)
    (scoped); plus per-widget builders (
    messageBuilder
    ,
    itemBuilder
    ) for a single instance.
Recurring traps the doc guards against:
  • (a) overriding a composite widget (
    messageItem
    builder,
    messageComposer
    builder,
    messageBuilder
    on
    StreamMessageListView
    ) silently drops the sub-features the default rendered — the incoming-message avatar, grouping, reactions, replies, status, or the send/voice/edit/slow-mode button — unless you read the default's
    build()
    and reproduce them (grouping state is available inside a custom
    messageItem
    via
    StreamMessageLayout.of(context)
    );
  • (b) model-driven title logic must live in one shared helper used by both the channel list
    itemBuilder
    and the header, so the two surfaces cannot diverge;
  • (c) route deliberately — bubble padding / color / shape live on
    StreamTheme
    (
    StreamTheme.messageItemTheme.bubble
    ); structural changes (send button outside the field, metadata inside the bubble, a bubble tail, a Slack-style flat row) need widget replacement (component factory or a per-widget builder).
The match is not done until you run, seed data that triggers every region, compare region-by-region against the reference on the real navigation path, and iterate (
design-matching.md
Step 5), deleting any throwaway verification scaffold — the UI must be as close to the reference as possible, not approximately like it. Implement every region, the composer included — never deliver a partial match with the rest labelled "known cosmetic gaps"; a region left at the SDK default is a FAIL, not a footnote. And work in batches: ground the pinned SDK version + local checkout once, read the source you need in one pass, implement all regions, then verify once on hot reload — don't rebuild-and-screenshot after every small edit.
如果请求包含目标外观 —— 附带截图、Figma框架,或者要求"做成WhatsApp/iMessage/Telegram/Slack/<某应用>的样子" —— 那么在进行功能开发(A或B跟踪路径)之前,需首先执行以下策略决策(组件化vs自定义):
  • 组件化 → 执行
    design-matching.md
    :完整阅读其流程部分 ——
    # Reference
    分隔线以上的所有内容(步骤1–5;可能需要分两次读取,因此需翻过分隔线截断的内容)—— 然后在实现时按区域查找其参考部分。
  • 自定义(直播/覆盖层/定制化) → 改为执行
    custom-ui.md
    —— 同样需要按区域严格执行,但机制不同。
本节其余部分为组件化场景(常见场景)。参考设计是各区域的清单(头部、编辑器按钮、时间戳+已读回执位置、气泡形状/尾部、日期分隔符、附件等),其中大多数与Stream默认值的差异是结构性的,而非仅颜色不同。切勿仅停留在背景和气泡颜色调整上 —— 这是已知的失败模式。首先分解每个区域(记录其尺寸,而非仅颜色),然后将每个区域归入以下两个维度之一:
  1. 主题定制 ——
    StreamTheme
    MaterialApp.theme.extensions
    上的
    ThemeExtension
    )负责设计基础(间距/圆角/排版/颜色)以及所有细粒度/叶子节点样式,包括整条消息行(
    messageItemTheme
    气泡/文本/附件/元数据、
    reactionsTheme
    reactionPickerTheme
    avatarTheme
    textInputTheme
    mediaViewerTheme
    等),而
    StreamChatThemeData
    (通过
    StreamChat(themeData:)
    传入)仅负责聊天复合组件插槽(三个头部、消息列表背景/壁纸、频道列表项、引用消息、线程卡片、投票主题)。
  2. 组件替换 —— 组件工厂,通过
    StreamComponentBuilders(...)
    上的核心命名插槽(约48个叶子节点插槽:
    messageBubble
    messageText
    reactions
    reactionPicker
    mediaViewer
    jumpToUnreadButton
    textInput
    avatar
    等)以及
    streamChatComponentBuilders(...) → extensions:
    上的聊天插槽(约30个复合插槽:
    messageItem
    messageComposer
    +子插槽、
    channelListItem
    、每个附件的构建器等)填充,传入
    StreamChat(componentBuilders: StreamComponentBuilders(...))
    (全局)或
    StreamComponentFactory(builders: …, child: …)
    (局部作用域);此外还有针对单个实例的每个组件构建器(
    messageBuilder
    itemBuilder
    )。
文档防范的常见陷阱:
  • (a) 覆盖复合组件
    messageItem
    构建器、
    messageComposer
    构建器、
    StreamMessageListView
    上的
    messageBuilder
    )会默认丢弃其原本具备的子功能—— incoming-message头像、分组、 reactions、回复、状态,或发送/语音/编辑/慢模式按钮—— 除非你阅读默认组件的
    build()
    方法并重现这些功能(自定义
    messageItem
    内可通过
    StreamMessageLayout.of(context)
    获取分组状态);
  • (b) 模型驱动的标题逻辑必须放在一个共享辅助工具中,供频道列表
    itemBuilder
    和头部同时使用,以确保两个界面不会出现不一致;
  • (c) 有目的地选择方式 —— 气泡内边距/颜色/形状属于**
    StreamTheme
    StreamTheme.messageItemTheme.bubble
    );结构性更改(发送按钮在输入框外、元数据在气泡内、气泡尾部、Slack风格平面行)需要
    组件替换**(组件工厂或单个组件构建器)。
匹配完成的标准是运行应用,生成触发所有区域的测试数据,在实际导航路径上逐区域与参考设计对比,并进行迭代
design-matching.md
步骤5),删除任何临时验证脚手架—— UI必须尽可能接近参考设计,而非近似。实现所有区域,包括编辑器—— 切勿交付仅部分匹配、其余部分标记为"已知视觉差距"的成果;保留SDK默认值的区域视为失败,而非脚注。并且分批工作:固定SDK版本+本地检出一次,一次性读取所需源码,实现所有区域,然后通过热重载一次性验证—— 不要每次小修改后都重新构建并截图。

Chat only: pick the UI strategy first (before any code)

仅聊天场景:先选择UI策略(编写代码前)

Stream Chat ships two layers, and choosing between them is an architecture decision that dwarfs any styling choice — getting it wrong wastes a day either way. So decide deliberately, and default to the pre-built components:
StrategyUse when the design is...MechanismRunbook
Pre-built UI components (
stream_chat_flutter
) — the default
A messenger: bubbles, or a channel list → conversation, or per-message avatar/timestamp/receipts/reactions/attachments. Social, marketplace, workplace, support, DMs. "Make it look like WhatsApp / iMessage / Telegram / Slack."Customize via the two axes — theming (
StreamTheme
for foundations + the message row/leaf widgets,
StreamChatThemeData
for the chat composite widgets) + widget replacement (the component factory
StreamComponentBuilders
/
streamChatComponentBuilders
/
StreamComponentFactory
, plus per-widget builders)
design-matching.md
Custom UI on
stream_chat_flutter_core
— the exception
Not a messenger: a flat bubble-less author-inline feed, an overlay/ticker on video, high-volume ephemeral livestream chat (Twitch / YouTube / Kalshi), live shopping, or anonymous/guest read-only viewers vastly outnumbering posters (→
livestream
channel type). Every message rendered identically; bespoke app chrome around it.
Build your own widgets on the headless
stream_chat_flutter_core
controllers (+ the low-level client); no
stream_chat_flutter
widgets
custom-ui.md
Lean hard toward components. They're built to be customized, and the litmus test is: if the two axes — theming (
StreamTheme
+
StreamChatThemeData
) + a few component-builder slots — could get there, it's a components job
— even strong messenger reskins. Pick custom only when matching the design would mean replacing the message row, composer, header, AND list all at once — i.e. you'd be using the SDK purely as a data source, not for any of its widgets. Over-choosing custom (rebuilding a worse messenger by hand, losing avatars/grouping/reactions/threads/attachments/typing/receipts/pickers) is the common, expensive mistake; over-choosing components costs a few hours of fighting layout. When unsure, build the components version first — it's faster to confirm-or-reject. And treat "livestream" / "live-shopping" as signals, not labels: they point to custom only when the shape matches (flat identical rows, overlay/ticker, high volume, read-only viewers) — a livestream app that wants a normal bubble/channel-list chat panel stays on components. This is the full decision rubric;
custom-ui.md
is the build runbook you follow after the decision lands on custom, not a doc you open to decide.
Workplace / Slack-style hybrid is a components job too. A Slack/Teams/Discord surface is a channel list + message list + composer, so it stays on the pre-built components — but two things differ from a messenger and must be matched, not punted: (1) the message row is flat and left-aligned (avatar-top rounded-square, an author·custom-status·timestamp header line, body, bottom reaction pills, and a thread-reply summary), with no incoming/outgoing bubble split — reproduce it by overriding the
messageItem
component builder (a composite slot — reproduce its sub-features); (2) the header and chrome are custom. The full workplace archetype is in
design-matching.md
. Workplace apps are also thread-first, so wire the thread-reply summary and thread screen.
The strategy also picks the channel type and permission model (e.g.
messaging
membership-gated for social/marketplace vs
livestream
public + anonymous viewers) — see
RULES.md
→ "Surface permission prerequisites proactively", and Step 0.5 → "Permissions awareness". Decide both axes together.
If it's genuinely unclear, ask one question:
Does this chat look like a standard messenger (channel list + bubbles), or a bespoke surface like livestream/overlay chat? It decides whether we customize the pre-built components or build custom UI on
stream_chat_flutter_core
.
Stream Chat提供两层架构,选择哪一层是比任何样式选择都重要的架构决策—— 选错会浪费一整天时间。因此需谨慎决策,默认选择预构建组件
策略适用场景实现机制操作手册
预构建UI组件 (
stream_chat_flutter
) —— 默认选项
信使类应用:气泡式聊天、频道列表→对话、每条消息的头像/时间戳/回执/reactions/附件。社交、 marketplace、职场、客服、私信。"做成WhatsApp/iMessage/Telegram/Slack的样子"。通过两个维度定制—— 主题定制(
StreamTheme
负责基础+消息行/叶子组件,
StreamChatThemeData
负责聊天复合组件)+ 组件替换(组件工厂
StreamComponentBuilders
/
streamChatComponentBuilders
/
StreamComponentFactory
,以及单个组件构建器)
design-matching.md
基于
stream_chat_flutter_core
的自定义UI
—— 例外情况
非信使类应用:无气泡的作者内联信息流、视频上的覆盖层/滚动提示、高流量临时直播聊天(Twitch/YouTube/Kalshi)、直播带货,或匿名/访客只读观众数量远超发帖者(→
livestream
频道类型)。每条消息渲染方式相同;应用周围有定制化界面。
在无头
stream_chat_flutter_core
控制器(+底层客户端)上构建自己的组件;不使用
stream_chat_flutter
组件
custom-ui.md
优先选择组件化方案。这些组件专为定制化设计,检验标准是:如果两个维度——主题定制(
StreamTheme
+
StreamChatThemeData
)+ 几个组件构建器插槽——能够实现需求,就属于组件化工作
—— 即使是大幅修改样式的信使类应用。仅当匹配设计需要同时替换消息行、编辑器、头部和列表时才选择自定义—— 即仅将SDK作为数据源,不使用其任何组件。过度选择自定义(手动构建更差的信使类应用,丢失头像/分组/reactions/线程/附件/输入状态/回执/选择器)是常见且代价高昂的错误;过度选择组件化仅需花费数小时调整布局。不确定时,先构建组件化版本—— 确认或否决的速度更快。并且将**"livestream"/"live-shopping"视为信号,而非标签**:只有当形态匹配(平面相同行、覆盖层/滚动提示、高流量、只读观众)时才指向自定义—— 需要正常气泡/频道列表聊天面板的直播应用仍使用组件化方案。这是完整的决策准则;
custom-ui.md
是决策确定为自定义后遵循的构建手册,而非用于决策的文档。
职场/Slack风格混合应用属于组件化工作。Slack/Teams/Discord界面是频道列表+消息列表+编辑器,因此仍使用预构建组件—— 但有两点与信使类应用不同,必须匹配,不能忽略:(1) 消息行是平面左对齐的(顶部圆角方形头像、作者·自定义状态·时间戳头部行、正文、底部reaction药丸线程回复摘要),无 incoming/outgoing气泡区分—— 通过覆盖
messageItem
组件构建器(复合插槽——重现其子功能)实现;(2) 头部和界面是定制化的。完整的职场原型在
design-matching.md
中。职场应用也以线程优先,因此需接入线程回复摘要和线程屏幕。
该策略还会选择频道类型和权限模型(例如,社交/marketplace使用
messaging
会员 gated 模式,直播使用
livestream
公开+匿名观众模式)—— 参见
RULES.md
→ "主动告知权限先决条件",以及步骤0.5 → "权限意识"。需同时确定两个维度。
如果确实不确定,可问一个问题:
这个聊天界面看起来像标准信使类应用(频道列表+气泡),还是像直播/覆盖层聊天这样的定制化界面?这将决定我们是定制预构建组件还是基于
stream_chat_flutter_core
构建自定义UI。

Disambiguation flow

歧义处理流程

If the request is ambiguous between build/integrate and reference lookup, ask one short question and wait:
Do you want me to wire this into the project, or just map the Flutter SDK pattern and widgets?
如果请求在构建/集成参考查询之间存在歧义,问一个简短问题并等待回复:
你希望我将此功能接入项目,还是仅梳理Flutter SDK的模式和组件?

After classification

分类后操作

  • Tracks A, B, D -> run Project signals once per session, then continue in
    builder.md
    and
    sdk.md
    . If the styling-depth flag was raised, run the design-match phase alongside per the UI-strategy decision —
    design-matching.md
    for the pre-built components (the common case; read its procedure half in full — everything above the
    # Reference
    divider, which may span two Reads — then Grep its Reference half per region) or
    custom-ui.md
    for a bespoke
    stream_chat_flutter_core
    surface (design-match rigor is a mandatory phase, not an optional add-on).
  • Track C -> skip the probe if the product + package are explicit. Only run it on demand if the SDK layer is ambiguous.
  • Track M -> run
    sendbird-migration.md
    : detect the existing Sendbird integration shape, swap packages/init/views/channels/messages, re-apply theming via the two axes, and verify design + functional fidelity per screen against the Sendbird original. Reuses Step 0.5 credentials and
    design-matching.md
    /
    custom-ui.md
    rigor; hands off to the shared data-migration runbook when the code migration is done.

  • A、B、D跟踪路径 -> 每次会话运行一次项目信号检测,然后继续执行
    builder.md
    sdk.md
    。如果触发了样式深度标记,需根据UI策略决策同步执行设计匹配阶段—— 预构建组件(常见场景)执行
    design-matching.md
    (完整阅读其流程部分——
    # Reference
    分隔线以上的所有内容,可能需要分两次读取——然后按区域查找其参考部分),定制化/直播/覆盖层场景执行
    custom-ui.md
  • C跟踪路径 -> 如果产品+包明确,跳过探查。仅当SDK层存在歧义时按需运行探查。
  • M跟踪路径 -> 执行
    sendbird-migration.md
    :检测现有Sendbird集成形态,替换包/初始化/视图/频道/消息,通过两个维度重新应用主题定制,并逐屏对比Sendbird原版验证设计+功能保真度。复用步骤0.5的凭证以及
    design-matching.md
    /
    custom-ui.md
    的严格要求;代码迁移完成后移交至共享数据迁移手册。

Step 0.5: Credentials, token, and seed data (tracks A, B, D — and Track M at phase M2)

步骤0.5:凭证、令牌和测试数据(A、B、D跟踪路径——以及M跟踪路径的M2阶段)

Run this once per session, right after intent classification, before the Project signals probe.
每次会话在意图分类后、项目信号探查前运行一次。

Goal

目标

Collect the Stream API key, a user token, and optionally seed channels or calls - all before touching code - so the app has real data to show from the first run.
收集Stream API密钥用户令牌,可选预创建频道或通话—— 在接触代码前完成所有这些操作,以便应用从首次运行开始就有真实数据展示。

Single upfront question (ask exactly once, then act immediately)

一次性前置问题(准确询问一次,然后立即执行)

Post one message asking all relevant things together. Do not split into multiple rounds.
For Chat projects:
To wire everything up with real data, I need a few quick answers:
  1. Credentials - Should I fetch your API key from the dashboard and generate a token via the Stream CLI, or will you paste them yourself?
  2. Token expiry - If I'm generating the token: should it expire? (e.g.
    1h
    ,
    1d
    ,
    30m
    ) or never expire?
  3. Seed channels - Should I pre-create a few channels with random usernames so the app has something to show immediately?
If you want to handle everything yourself, just paste your API key and token and tell me whether to seed channels.
For Video projects (calls are ephemeral - no seeding needed):
To wire everything up, I need a couple of quick answers:
  1. Credentials - Should I fetch your API key from the dashboard and generate a token via the Stream CLI, or will you paste them yourself?
  2. Token expiry - If I'm generating the token: should it expire? (e.g.
    1h
    ,
    1d
    ,
    30m
    ) or never expire?
If you want to handle everything yourself, just paste your API key and token.
Guest-viewer requirement — surface this BEFORE building any app that signs viewers in as guests. A guest connects with the
guest
role, which by default has minimal capabilities. On the
livestream
call type guests cannot even read or join a call until the integrator grants those capabilities to the
guest
role. When a guest-based viewer flow is in scope, tell the integrator it is a prerequisite to grant the
guest
role
read-call
and
join-call
(plus
create-call
if a viewer may open the call before the host) on the relevant call type via Stream Dashboard → Video & Audio → Call Types → <type> → Roles & Permissions (or the API), or to use authenticated
User.regular
viewers instead. Details:
references/VIDEO-FLUTTER.md
→ Guest users, and
references/LIVESTREAM-FLUTTER.md
→ Roles, permissions, and backstage security.
For Feeds projects (no pre-built UI; feed groups required):
Ask one message with all setup questions together — do not split into rounds:
To wire everything up, I need a few quick answers:
  1. Credentials - Should I fetch your API key from the dashboard and generate a token via the Stream CLI, or will you paste them yourself?
  2. Token expiry - If I'm generating the token: should it expire? (e.g.
    1h
    ,
    1d
    ,
    30m
    ) or never expire?
  3. Feed groups - I need to create 3 feed groups in your Stream project (user, timeline, notification). Should I set these up automatically, or have you already created them?
  4. Seed posts - Should I add a few sample posts so the feed has content from the first run?
If you want to handle credentials yourself, just paste your API key and token.
Once the user replies, execute all steps without pausing. For feed groups, if the user said "set up automatically":
bash
getstream api CreateFeedGroup --request '{"id": "user", "type": "flat"}'
getstream api CreateFeedGroup --request '{"id": "timeline", "type": "flat"}'
getstream api CreateFeedGroup --request '{"id": "notification", "type": "notification"}'
If the CLI commands fail (the Feeds API may use different endpoints than Chat), tell the user once:
Please create these in Stream Dashboard → Activity Feeds → Feed Groups:
user
(Flat),
timeline
(Flat),
notification
(Notification).
For Feeds projects, always generate two separate helpers in
main
after
connect()
:
  1. _setupFollows(client)
    always called, unconditionally. Makes
    timeline
    follow
    user
    so the user's own posts appear there. Do not merge this into seed logic — once seed data exists the guard returns early and the follow call never runs.
  2. _seedPosts(client)
    — only if the user said yes to seeding. Adds sample activities and exits early if data already exists.
See
references/FEEDS-FLUTTER.md
for both implementations.
The package is
stream_feeds: ^0.5.1
— not the deprecated
stream_feed
or
stream_feed_flutter_core
.
发布一条消息,一次性询问所有相关问题。不要拆分多次询问。
聊天项目:
为了接入真实数据,我需要几个快速回复:
  1. 凭证 - 我应该从控制台获取你的API密钥并通过Stream CLI生成令牌,还是你自行粘贴?
  2. 令牌有效期 - 如果我生成令牌:是否需要设置有效期?(例如
    1h
    1d
    30m
    )还是永不过期?
  3. 测试频道 - 是否需要预创建几个带有随机用户名的频道,以便应用立即有内容展示?
如果你想自行处理所有事项,只需粘贴你的API密钥和令牌,并告知我是否需要预创建测试频道。
视频项目(通话是临时的——无需预创建测试数据):
为了完成接入,我需要几个快速回复:
  1. 凭证 - 我应该从控制台获取你的API密钥并通过Stream CLI生成令牌,还是你自行粘贴?
  2. 令牌有效期 - 如果我生成令牌:是否需要设置有效期?(例如
    1h
    1d
    30m
    )还是永不过期?
如果你想自行处理所有事项,只需粘贴你的API密钥和令牌。
访客查看者要求——在构建任何以访客身份登录查看者的应用之前告知。访客以
guest
角色连接,默认权限极低。对于
livestream
通话类型,访客甚至无法读取或加入通话,直到集成者为
guest
角色授予相应权限。当涉及基于访客的查看者流程时,告知集成者这是先决条件,需通过Stream控制台→视频与音频→通话类型→<类型>→角色与权限(或API)为
guest
角色授予
read-call
join-call
权限(如果查看者可能在主持人之前打开通话,还需授予
create-call
权限),或使用已认证的
User.regular
查看者。详细信息:
references/VIDEO-FLUTTER.md
→ 访客用户,以及
references/LIVESTREAM-FLUTTER.md
→ 角色、权限和后台安全。
信息流项目(无预构建UI;需要信息流组):
一次性询问所有设置问题—— 不要拆分多次询问:
为了完成接入,我需要几个快速回复:
  1. 凭证 - 我应该从控制台获取你的API密钥并通过Stream CLI生成令牌,还是你自行粘贴?
  2. 令牌有效期 - 如果我生成令牌:是否需要设置有效期?(例如
    1h
    1d
    30m
    )还是永不过期?
  3. 信息流组 - 我需要在你的Stream项目中创建3个信息流组(user、timeline、notification)。是否需要我自动设置,还是你已创建完成?
  4. 测试帖子 - 是否需要添加一些示例帖子,以便信息流从首次运行开始就有内容?
如果你想自行处理凭证,只需粘贴你的API密钥和令牌。
用户回复后,无需停顿执行所有步骤。对于信息流组,如果用户说"自动设置":
bash
getstream api CreateFeedGroup --request '{"id": "user", "type": "flat"}'
getstream api CreateFeedGroup --request '{"id": "timeline", "type": "flat"}'
getstream api CreateFeedGroup --request '{"id": "notification", "type": "notification"}'
如果CLI命令失败(Feeds API可能使用与Chat不同的端点),告知用户一次:
请在Stream控制台→活动流→信息流组中创建这些组:
user
(Flat)、
timeline
(Flat)、
notification
(Notification)。
对于信息流项目,连接后始终在
main
中生成两个独立的辅助工具:
  1. _setupFollows(client)
    —— 始终无条件调用。使
    timeline
    关注
    user
    ,以便用户自己的帖子显示在其中。不要将此合并到测试数据逻辑中—— 一旦测试数据存在,防护逻辑会提前返回,关注调用将不会执行。
  2. _seedPosts(client)
    —— 仅当用户同意预创建测试数据时调用。添加示例活动,如果数据已存在则提前退出。
两个工具的实现参见
references/FEEDS-FLUTTER.md
使用的包是
stream_feeds: ^0.5.1
—— 而非已弃用的
stream_feed
stream_feed_flutter_core

After the user replies - act without further prompting

用户回复后——无需进一步提示立即执行

Once the user answers, execute all CLI steps in sequence without pausing for confirmation between them. Narrate each step briefly as you go (one line per action), but do not stop to ask "shall I continue?".
用户回复后,按顺序执行所有CLI步骤无需在步骤间停顿等待确认。执行每个步骤时简要说明(每个操作一行),但不要停下来问"是否继续?"。

Step A - API key

步骤A - API密钥

bash
getstream env --target flutter
This writes the public API key to
dart_defines.json
; the app reads it via
String.fromEnvironment('STREAM_API_KEY')
and is run with
flutter run --dart-define-from-file=dart_defines.json
. If the command returns a 401 error, the CLI session has expired - run
getstream login
to re-authenticate, then retry.
If
getstream
is not installed
(
command not found
): ask the user to install it from https://getstream.io and wait. Or, if the user prefers, skip the CLI entirely and have them paste the API key + a token per user (Dashboard -> Explorer has a token generator). Decide based on the user's answer to the upfront credentials question; don't stall.
bash
getstream env --target flutter
此命令会将公开API密钥写入
dart_defines.json
;应用通过
String.fromEnvironment('STREAM_API_KEY')
读取,并使用
flutter run --dart-define-from-file=dart_defines.json
运行。如果命令返回401错误,说明CLI会话已过期—— 运行
getstream login
重新认证,然后重试。

Step B - Token

步骤B - 令牌

bash
undefined
bash
undefined

Never-expiring

永不过期

getstream token <user_id>
getstream token <user_id>

Expiring

有有效期

getstream token <user_id> --ttl <duration>

Hold the token in context. Use it (and the API key) in every code snippet - no placeholder strings.
getstream token <user_id> --ttl <duration>

将令牌保存在上下文环境中。在所有代码片段中使用它(和API密钥)—— 不要使用占位符字符串。

Step C - Seed channels (only if the user said yes)

步骤C - 测试频道(仅当用户同意时)

Create 3-5 channels with random realistic usernames. Use
messaging
as the default channel type.
Sub-step C1 — upsert all users (seed users + the token user):
bash
getstream api UpdateUsers --request '{
  "users": {
    "<token_user_id>": {"id": "<token_user_id>", "name": "<Display Name>"},
    "alice": {"id": "alice", "name": "Alice"},
    "bob":   {"id": "bob",   "name": "Bob"},
    "carol": {"id": "carol", "name": "Carol"},
    "dave":  {"id": "dave",  "name": "Dave"}
  }
}'
Sub-step C2 — create each channel (no members in the body; members are added in C3):
bash
getstream api GetOrCreateChannel --type messaging --id <channel-id> \
  --request '{"data": {"custom": {"name": "<Channel Name>"}}}'
Repeat for each channel (e.g.
general
,
random
,
team-alpha
).
Sub-step C3 — add members to each channel using
add_members
. The token user must be in every channel so the
Filter.in_('members', [userId])
query in the app returns results.
bash
getstream api UpdateChannel --type messaging --id <channel-id> \
  --request '{
    "add_members": [
      {"user_id": "<token_user_id>"},
      {"user_id": "alice"},
      {"user_id": "bob"}
    ],
    "user_id": "<token_user_id>"
  }'
Generate short memorable channel IDs (e.g.
general
,
random
,
team-alpha
) and use a small set of random usernames (e.g.
alice
,
bob
,
carol
,
dave
). The token user must be added to every channel — the channel list filter is
Filter.in_('members', [tokenUserId])
and will return nothing if the user is absent.
After seeding, print a brief summary:
Created channels:
general
(token_user, alice, bob),
random
(token_user, carol, dave),
team-alpha
(token_user, alice, carol)
创建3-5个带有随机真实用户名的频道。默认使用
messaging
频道类型。
子步骤C1 —— 更新所有用户(测试用户+令牌用户):
bash
getstream api UpdateUsers --request '{
  "users": {
    "<token_user_id>": {"id": "<token_user_id>", "name": "<显示名称>"},
    "alice": {"id": "alice", "name": "Alice"},
    "bob":   {"id": "bob",   "name": "Bob"},
    "carol": {"id": "carol", "name": "Carol"},
    "dave":  {"id": "dave",  "name": "Dave"}
  }
}'
子步骤C2 —— 创建每个频道(请求体中不包含成员;成员在C3中添加):
bash
getstream api GetOrCreateChannel --type messaging --id <channel-id> \
  --request '{"data": {"custom": {"name": "<频道名称>"}}}'
为每个频道重复此操作(例如
general
random
team-alpha
)。
子步骤C3 —— 使用
add_members
为每个频道添加成员
。令牌用户必须加入每个频道,以便应用中的
Filter.in_('members', [userId])
查询返回结果。
bash
getstream api UpdateChannel --type messaging --id <channel-id> \
  --request '{
    "add_members": [
      {"user_id": "<token_user_id>"},
      {"user_id": "alice"},
      {"user_id": "bob"}
    ],
    "user_id": "<token_user_id>"
  }'
生成简短易记的频道ID(例如
general
random
team-alpha
),并使用一组随机用户名(例如
alice
bob
carol
dave
)。令牌用户必须加入每个频道—— 频道列表过滤器是
Filter.in_('members', [tokenUserId])
,如果用户不在频道中则返回空结果。
预创建完成后,打印简要摘要:
创建的频道:
general
(token_user, alice, bob)、
random
(token_user, carol, dave)、
team-alpha
(token_user, alice, carol)

Step D - Proceed automatically

步骤D - 自动继续

After all CLI steps succeed, continue without pausing - no additional prompt needed: tracks A/B/D move straight to Project signals and then into
builder.md
; Track M returns to
sendbird-migration.md
(phase M2). If any CLI step fails, explain the error briefly and ask the user to paste the missing value manually before continuing.
所有CLI步骤成功后,无需停顿继续执行—— 无需额外提示:A/B/D跟踪路径直接进入项目信号检测,然后执行
builder.md
;M跟踪路径返回
sendbird-migration.md
(M2阶段)。如果任何CLI步骤失败,简要说明错误并请用户手动粘贴缺失的值后继续。

What NOT to do

禁止操作

  • Never put the API secret in app code - the CLI uses it server-side only.
  • Never invent or fabricate credentials.
  • Never ask "should I continue?" between Step A, B, C, and D - execute the whole sequence once the user's upfront answers are in.
  • 切勿将API 密钥放入应用代码中—— CLI仅在服务器端使用它。
  • 切勿编造或伪造凭证。
  • 切勿在步骤A、B、C、D之间问"是否继续?"—— 用户回复前置问题后执行整个序列。

Permissions awareness (Chat - surface proactively)

权限意识(聊天场景——主动告知)

Stream Chat checks permissions per role, per scope on every client-side call — but server-side calls (the CLI and your backend, using the API secret) bypass all checks. That asymmetry is the #1 source of "it worked when you seeded it, but the app 403s": seeding channels via the CLI succeeds regardless of grants, then the same query/join from the app hits the connected user's role and fails.
When the app you're about to build does anything beyond chatting inside channels the user is already a member of, tell the integrator about the relevant grants before writing the feature — don't wait for a runtime 403. Map the scenario to the grant:
App behaviour you're buildingGrant the connecting role needs on the channel typeDefault
messaging
for
user
/
guest
Discover / browse groups the user didn't create (
queryChannels
without a
members
filter)
Read Channel
(
ReadChannel
)
often off
Join an existing group (
channel.addMembers([myId])
)
Add Own Channel Membership
(
AddOwnChannelMembership
)
often off
Leave a group (
channel.removeMembers([myId])
)
Remove Own Channel Membership
(
RemoveOwnChannelMembership
)
varies
Create a group
Create Channel
(
CreateChannel
)
usually on
guest
users (name-only / no-backend sign-in) are stricter than
user
— if the app uses guest auth, the same grants must be added to the
guest
role too. Point the integrator to Dashboard → Chat → Roles & Permissions (permissions v2) for the role +
messaging
type, or
UpdateChannelType
via API/CLI. Full detail and the exact error string:
references/CHAT-FLUTTER.md
→ Channel permissions & roles (custom-UI builds:
references/CHAT-CORE.md
).
This is a prompt, not a blocker — build the feature as requested, but call out the prerequisite in the same turn so discover/join/create don't silently fail on first run.

Stream Chat会按角色、按范围检查每个客户端调用的权限—— 但服务器端调用(CLI和你的后端,使用API密钥)会绕过所有检查。这种不对称是"预创建时正常,但应用运行时403错误"的头号原因:通过CLI预创建频道无论权限如何都能成功,但应用中相同的查询/加入操作会受连接用户角色限制而失败。
当你要构建的应用除了在用户已加入的频道内聊天之外还有其他功能时,在编写功能之前告知集成者相关权限要求——不要等到运行时出现403错误才说明。将场景映射到权限:
你要构建的应用行为连接角色在频道类型上需要的权限
messaging
类型默认
user
/
guest
权限
发现/浏览用户未创建的群组(不带
members
过滤器的
queryChannels
Read Channel
(读取频道)
通常关闭
加入现有群组
channel.addMembers([myId])
Add Own Channel Membership
(添加自身频道成员)
通常关闭
离开群组
channel.removeMembers([myId])
Remove Own Channel Membership
(移除自身频道成员)
各不相同
创建群组
Create Channel
(创建频道)
通常开启
guest
用户(仅用户名/无后端登录)比
user
用户限制更严格—— 如果应用使用访客认证,相同权限必须添加到**
guest
角色。指引集成者前往控制台→聊天→角色与权限**(权限v2)设置角色+
messaging
类型,或通过API/CLI使用
UpdateChannelType
。详细信息和确切错误字符串:
references/CHAT-FLUTTER.md
→ 频道权限与角色(自定义UI构建:
references/CHAT-CORE.md
)。
这是提示,而非阻塞—— 按要求构建功能,但在同一轮告知前置条件,以便发现/加入/创建功能首次运行时不会静默失败。

Project signals (tracks A/B/D/M - once per session; Track C on demand only)

项目信号检测(A/B/D/M跟踪路径——每次会话一次;C跟踪路径按需运行)

Read-only local probe. Use it to detect whether the user is in a Flutter project or an empty directory.
bash
bash -c 'echo "=== FLUTTER ==="; find . -maxdepth 2 -name "pubspec.yaml" -print 2>/dev/null; echo "=== STREAM ==="; grep -rE "stream_chat|stream_video|stream_feed" . --include="pubspec.yaml" -l 2>/dev/null; echo "=== EMPTY ==="; test -z "$(ls -A 2>/dev/null)" && echo "EMPTY_CWD" || echo "NON_EMPTY"'
Hold the result in conversation context. Don't re-run it unless the user changes directory or the project shape clearly changed.
Use the result to produce a one-line status, for example:
  • Flutter app detected - stream_chat_flutter already in pubspec.yaml
  • Flutter app detected - stream_video_flutter already in pubspec.yaml
  • Flutter app detected - stream_feed already in pubspec.yaml
  • Flutter app detected - no Stream dependency yet, ready to install
  • No Flutter project found - user needs to run flutter create first
只读本地探查。用于检测用户是否在Flutter项目或空目录中。
bash
bash -c 'echo "=== FLUTTER ==="; find . -maxdepth 2 -name "pubspec.yaml" -print 2>/dev/null; echo "=== STREAM ==="; grep -rE "stream_chat|stream_video|stream_feed" . --include="pubspec.yaml" -l 2>/dev/null; echo "=== EMPTY ==="; test -z "$(ls -A 2>/dev/null)" && echo "EMPTY_CWD" || echo "NON_EMPTY"'
将结果保存在对话上下文中。除非用户切换目录或项目形态明显变化,否则不要重新运行。
使用结果生成一行状态,例如:
  • 检测到Flutter应用 - pubspec.yaml中已存在stream_chat_flutter
  • 检测到Flutter应用 - pubspec.yaml中已存在stream_video_flutter
  • 检测到Flutter应用 - pubspec.yaml中已存在stream_feed
  • 检测到Flutter应用 - 尚未添加Stream依赖,可开始安装
  • 未检测到Flutter项目 - 用户需要先运行flutter create

Version prerequisite (Chat - existing project)

版本要求(聊天场景——现有项目)

When a Stream Chat dependency is already present, check the resolved version (
pubspec.yaml
constraint or the
version:
in
pubspec.lock
). These skills target
stream_chat_flutter
/
stream_chat_flutter_core
v10 only.
If the project is pinned to 9.x or earlier, stop before editing code and tell the user:
Your project uses
stream_chat_flutter
v<found>. These instructions cover v10. A lot changed between v9 and v10 (widget names, controllers, theming, reaction/delete APIs). The official migration guides are at https://github.com/GetStream/stream-chat-flutter/tree/master/migrations — refer to the relevant version's guide for step-by-step instructions. Once you're on v10, I can continue with the full feature set.
If the user asks for help with the migration itself, fetch the relevant migration doc from the URL above and walk them through it step by step.
Only proceed with Chat work once the project resolves a v10 (
^10.0.0
) dependency. New installs always use
^10.0.0
, so this check applies to existing integrations only.

当已存在Stream Chat依赖时,检查已解析的版本(
pubspec.yaml
约束或
pubspec.lock
中的
version:
)。这些技能仅针对
stream_chat_flutter
/
stream_chat_flutter_core
v10版本
。如果项目固定为9.x或更早版本,在编辑代码前停止并告知用户:
你的项目使用
stream_chat_flutter
v<检测到的版本>。本指南适用于v10版本。v9和v10之间变化很大(组件名称、控制器、主题定制、reaction/删除API)。官方迁移指南位于https://github.com/GetStream/stream-chat-flutter/tree/master/migrations —— 请参考对应版本的指南获取分步说明。升级到v10后,我可以继续提供完整功能支持。
如果用户请求帮助进行迁移,从上述URL获取相关迁移文档并逐步引导他们完成。
仅当项目解析为v10(
^10.0.0
)依赖时才继续聊天相关工作。新安装始终使用
^10.0.0
,因此此检查仅适用于现有集成。

Module map

模块映射

TrackModule(s)
A - New app
builder.md
+
sdk.md
+ relevant reference files
B - Existing app
builder.md
+
sdk.md
+ relevant reference files
C - Reference lookup
sdk.md
+ relevant reference files
D - Bootstrap / setup
builder.md
+
sdk.md
M - Migrate from Sendbird
sendbird-migration.md
(+
design-matching.md
/
custom-ui.md
,
sdk.md
,
../stream/sendbird-data-migration.md
)
Styling-depth flag (screenshot/Figma/"look like")Pick the UI strategy first (Step 0). Components →
design-matching.md
(procedure half in full — everything above the
# Reference
divider, may span two Reads; Reference half per region); bespoke/livestream/overlay →
custom-ui.md
. Run before feature work on Track A/B; region-by-region rigor + verification loop either way
Feeds note (Track A/B): Use Twitter-style UI by default. Only deviate if the user explicitly requests a different style (e.g., "Instagram grid", "Reddit-style votes").

跟踪路径模块
A - 新应用
builder.md
+
sdk.md
+ 相关参考文件
B - 现有应用
builder.md
+
sdk.md
+ 相关参考文件
C - 参考查询
sdk.md
+ 相关参考文件
D - 初始化/配置
builder.md
+
sdk.md
M - 从Sendbird迁移
sendbird-migration.md
(+
design-matching.md
/
custom-ui.md
,
sdk.md
,
../stream/sendbird-data-migration.md
)
样式深度标记(截图/Figma/"做成...样子")首先选择UI策略(步骤0)。组件化→
design-matching.md
(完整阅读流程部分——
# Reference
分隔线以上的所有内容,可能需要分两次读取;按区域查找参考部分);定制化/直播/覆盖层→
custom-ui.md
。在A/B跟踪路径的功能开发之前运行;无论哪种情况都需按区域严格执行+验证循环
信息流注意事项(A/B跟踪路径): 默认使用Twitter风格UI。仅当用户明确要求不同风格时才更改(例如"Instagram网格"、"Reddit风格投票")。

Reference layout

参考布局

Shared Flutter/Dart patterns live in
sdk.md
.
Product and package specifics live under
references/
using a flat naming scheme:
  • Reference:
    references/<PRODUCT>-<PACKAGE>.md
  • Blueprints:
    references/<PRODUCT>-<PACKAGE>-blueprints.md
Current extracted modules:
  • Chat + pre-built UI (
    stream_chat_flutter
    ):
    references/CHAT-FLUTTER.md
    +
    references/CHAT-FLUTTER-blueprints.md
  • Chat + custom UI (
    stream_chat_flutter_core
    ):
    references/CHAT-CORE.md
    +
    references/CHAT-CORE-blueprints.md
  • Chat advanced (push, offline, lifecycle — both UI tiers):
    references/CHAT-ADVANCED-FLUTTER.md
    +
    references/CHAT-ADVANCED-FLUTTER-blueprints.md
    - push notifications, offline/local persistence, connection lifecycle & backgrounding
  • Video (
    stream_video_flutter
    ):
    references/VIDEO-FLUTTER.md
    +
    references/VIDEO-FLUTTER-blueprints.md
  • Livestream (
    stream_video_flutter
    ):
    references/LIVESTREAM-FLUTTER.md
    +
    references/LIVESTREAM-FLUTTER-blueprints.md
  • Video advanced use cases (
    stream_video_flutter
    ):
    references/VIDEO-ADVANCED-FLUTTER.md
    +
    references/VIDEO-ADVANCED-FLUTTER-blueprints.md
    - audio rooms, multicall, chat+video, livestream feed, querying/events/preferences/moderation
  • Ringing / incoming calls + push (
    stream_video_flutter
    +
    stream_video_push_notification
    ):
    references/RINGING-FLUTTER.md
    +
    references/RINGING-FLUTTER-blueprints.md
    - outgoing ring, foreground/background/terminated incoming, CallKit (iOS) + FCM (Android)
  • Feeds (
    stream_feed
    /
    stream_feed_flutter_core
    ):
    references/FEEDS-FLUTTER.md
    +
    references/FEEDS-FLUTTER-blueprints.md
Additional Stream product coverage should stay in this naming family instead of creating more top-level skills.

共享Flutter/Dart模式位于**
sdk.md
**中。
产品和包的具体内容位于**
references/
**目录下,采用扁平命名方案:
  • 参考文档:
    references/<PRODUCT>-<PACKAGE>.md
  • 蓝图:
    references/<PRODUCT>-<PACKAGE>-blueprints.md
当前已提取的模块:
  • 聊天+预构建UI (
    stream_chat_flutter
    ):
    references/CHAT-FLUTTER.md
    +
    references/CHAT-FLUTTER-blueprints.md
  • 聊天+自定义UI (
    stream_chat_flutter_core
    ):
    references/CHAT-CORE.md
    +
    references/CHAT-CORE-blueprints.md
  • 聊天高级功能(推送、离线、生命周期——两个UI层级):
    references/CHAT-ADVANCED-FLUTTER.md
    +
    references/CHAT-ADVANCED-FLUTTER-blueprints.md
    - 推送通知、离线/本地持久化、连接生命周期与后台运行
  • 视频 (
    stream_video_flutter
    ):
    references/VIDEO-FLUTTER.md
    +
    references/VIDEO-FLUTTER-blueprints.md
  • 直播 (
    stream_video_flutter
    ):
    references/LIVESTREAM-FLUTTER.md
    +
    references/LIVESTREAM-FLUTTER-blueprints.md
  • 视频高级用例 (
    stream_video_flutter
    ):
    references/VIDEO-ADVANCED-FLUTTER.md
    +
    references/VIDEO-ADVANCED-FLUTTER-blueprints.md
    - 音频房间、多通话、聊天+视频、直播流、查询/事件/偏好/审核
  • 来电响铃+推送 (
    stream_video_flutter
    +
    stream_video_push_notification
    ):
    references/RINGING-FLUTTER.md
    +
    references/RINGING-FLUTTER-blueprints.md
    - 去电响铃、前台/后台/终止状态下来电、CallKit(iOS)+ FCM(Android)
  • 信息流 (
    stream_feed
    /
    stream_feed_flutter_core
    ):
    references/FEEDS-FLUTTER.md
    +
    references/FEEDS-FLUTTER-blueprints.md
新增Stream产品覆盖内容应保持此命名规则,而非创建更多顶级技能。

Track A - New app

A跟踪路径 - 新应用

Full detail:
builder.md
- use the new-project path.
PhaseNameWhat you do
A1DetectRun Project signals. If there is no Flutter app yet, tell the user to run
flutter create my_app
first.
A2Choose laneConfirm package choice:
stream_chat_flutter
(pre-built UI, fastest),
stream_chat_flutter_core
(custom UI),
stream_video_flutter
(video/livestream), or
stream_feed
/
stream_feed_flutter_core
(activity feeds, no pre-built UI). For Chat, this is the same components-vs-custom call as Step 0's "pick the UI strategy first" — default hard to
stream_chat_flutter
; pick core only for genuinely non-messenger surfaces (
custom-ui.md
). For Feeds, default to Twitter-style UI.
A3Install + wireFollow
builder.md
+
sdk.md
, then load only the needed reference files.
A4VerifyConfirm
flutter pub get
succeeds, client connects, and first screen renders. If the app discovers/joins channels or uses guest auth, re-state the permission prerequisite (Step 0.5 → Permissions awareness) so those flows don't 403 on first run.

详细信息:
builder.md
- 使用新项目路径
阶段名称操作内容
A1检测运行项目信号检测。如果尚未创建Flutter应用,告知用户先运行
flutter create my_app
A2选择方向确认包选择:
stream_chat_flutter
(预构建UI,最快)、
stream_chat_flutter_core
(自定义UI)、
stream_video_flutter
(视频/直播),或
stream_feed
/
stream_feed_flutter_core
(活动流,无预构建UI)。对于聊天场景,这与步骤0中"先选择UI策略"的组件化vs.custom决策相同—— 默认优先选择
stream_chat_flutter
;仅针对真正的非信使类界面选择core(
custom-ui.md
)。对于信息流场景,默认使用Twitter风格UI。
A3安装+接入遵循
builder.md
+
sdk.md
,然后仅加载所需参考文件。
A4验证确认
flutter pub get
成功、客户端连接、首屏渲染。如果应用发现/加入频道或使用访客认证,重新说明权限先决条件(步骤0.5 → 权限意识),以便这些流程首次运行时不会403错误。

Track B - Existing app

B跟踪路径 - 现有应用

Full detail:
builder.md
- use the existing-project path.
PhaseNameWhat you do
B1DetectRun Project signals and inspect the existing app structure before editing.
B2PreserveKeep the current navigation, state management, and widget architecture unless the user asks for a change.
B3IntegrateUse
sdk.md
for shared wiring, then load only the needed reference files.
B4VerifyConfirm the requested Stream flow builds and renders inside the existing app. If it discovers/joins channels or uses guest auth, re-state the permission prerequisite (Step 0.5 → Permissions awareness) so those flows don't 403 on first run.

详细信息:
builder.md
- 使用现有项目路径
阶段名称操作内容
B1检测运行项目信号检测并检查现有应用结构后再编辑。
B2保留保留当前导航、状态管理和组件架构,除非用户要求更改。
B3集成使用
sdk.md
进行共享接入,然后仅加载所需参考文件。
B4验证确认请求的Stream流程在现有应用中构建并渲染成功。如果应用发现/加入频道或使用访客认证,重新说明权限先决条件(步骤0.5 → 权限意识),以便这些流程首次运行时不会403错误。

Track C - Reference lookup

C跟踪路径 - 参考查询

Load only the relevant files for the requested package.
  • Shared lifecycle / auth / state / client-ownership patterns ->
    sdk.md
  • Chat advanced production concerns — push notifications, offline/local persistence, connection lifecycle & backgrounding (both UI tiers) ->
    references/CHAT-ADVANCED-FLUTTER.md
  • Chat advanced wiring blueprints (FCM setup + background handler, persistence init, lazy-connect gate) ->
    references/CHAT-ADVANCED-FLUTTER-blueprints.md
  • Chat pre-built UI setup, widgets, theming, member/user lists, message search, composer flags (voice/polls/drafts), filter operators, permissions ->
    references/CHAT-FLUTTER.md
  • Chat pre-built UI widget blueprints ->
    references/CHAT-FLUTTER-blueprints.md
  • Chat custom UI setup and controllers ->
    references/CHAT-CORE.md
  • Chat custom UI widget blueprints ->
    references/CHAT-CORE-blueprints.md
  • Video setup, call types, controls, state, StreamCallContainer ->
    references/VIDEO-FLUTTER.md
  • Video widget blueprints (entry point, join, call container, controls, participant tile) ->
    references/VIDEO-FLUTTER-blueprints.md
  • Livestream SDK patterns (call type, backstage, goLive/stopLive, HLS) ->
    references/LIVESTREAM-FLUTTER.md
  • Livestream widget blueprints (mode selection, creator, WebRTC viewer, HLS viewer) ->
    references/LIVESTREAM-FLUTTER-blueprints.md
  • Video advanced patterns (audio rooms, multicall, chat+video wiring, queryCalls, call events, preferences, moderation, session timers, network handling) ->
    references/VIDEO-ADVANCED-FLUTTER.md
  • Video advanced use-case blueprints (audio room screen, TikTok-style livestream feed, floating call panel, chat-with-video) ->
    references/VIDEO-ADVANCED-FLUTTER-blueprints.md
  • Ringing SDK patterns (push-enabled init, outgoing ring, incoming foreground/background/terminated, CallKit/FCM setup, accept/reject/end, customization, missed calls) ->
    references/RINGING-FLUTTER.md
  • Ringing blueprints (push init, background FCM handler, home-screen observers, outgoing ring, call screen, iOS AppDelegate, Android manifest/Gradle) ->
    references/RINGING-FLUTTER-blueprints.md
  • Feeds SDK setup, StreamFeedClient, feed types, activities, reactions, follow/unfollow, realtime ->
    references/FEEDS-FLUTTER.md
  • Feeds widget blueprints (Twitter-style by default: home feed, activity card, compose, profile, notifications; also Instagram/Reddit variants) ->
    references/FEEDS-FLUTTER-blueprints.md

仅加载所请求包的相关文件。
  • 共享生命周期/认证/状态/客户端所有权模式 ->
    sdk.md
  • 聊天高级生产问题 —— 推送通知、离线/本地持久化、连接生命周期与后台运行(两个UI层级)->
    references/CHAT-ADVANCED-FLUTTER.md
  • 聊天高级接入蓝图(FCM设置+后台处理器、持久化初始化、延迟连接门)->
    references/CHAT-ADVANCED-FLUTTER-blueprints.md
  • 聊天预构建UI设置、组件、主题定制、成员/用户列表、消息搜索、编辑器标记(语音/投票/草稿)、过滤运算符、权限 ->
    references/CHAT-FLUTTER.md
  • 聊天预构建UI组件蓝图 ->
    references/CHAT-FLUTTER-blueprints.md
  • 聊天自定义UI设置和控制器 ->
    references/CHAT-CORE.md
  • 聊天自定义UI组件蓝图 ->
    references/CHAT-CORE-blueprints.md
  • 视频设置、通话类型、控件、状态、StreamCallContainer ->
    references/VIDEO-FLUTTER.md
  • 视频组件蓝图(入口点、加入、通话容器、控件、参与者卡片)->
    references/VIDEO-FLUTTER-blueprints.md
  • 直播SDK模式(通话类型、后台、goLive/stopLive、HLS)->
    references/LIVESTREAM-FLUTTER.md
  • 直播组件蓝图(模式选择、创建者、WebRTC查看者、HLS查看者)->
    references/LIVESTREAM-FLUTTER-blueprints.md
  • 视频高级模式(音频房间、多通话、聊天+视频接入、queryCalls、通话事件、偏好、审核、会话计时器、网络处理)->
    references/VIDEO-ADVANCED-FLUTTER.md
  • 视频高级用例蓝图(音频房间屏幕、TikTok风格直播流、浮动通话面板、聊天+视频)->
    references/VIDEO-ADVANCED-FLUTTER-blueprints.md
  • 来电响铃SDK模式(推送启用初始化、去电响铃、前台/后台/终止状态下来电、CallKit/FCM设置、接听/拒绝/结束、定制化、未接来电)->
    references/RINGING-FLUTTER.md
  • 来电响铃蓝图(推送初始化、后台FCM处理器、主屏幕观察者、去电响铃、通话屏幕、iOS AppDelegate、Android清单/Gradle)->
    references/RINGING-FLUTTER-blueprints.md
  • 信息流SDK设置、StreamFeedClient、信息流类型、活动、reactions、关注/取消关注、实时 ->
    references/FEEDS-FLUTTER.md
  • 信息流组件蓝图(默认Twitter风格:首页信息流、活动卡片、撰写、个人资料、通知;也包含Instagram/Reddit变体)->
    references/FEEDS-FLUTTER-blueprints.md

Track D - Bootstrap / setup

D跟踪路径 - 初始化/配置

Use when the user wants the install and wiring path more than a feature build:
  • detect the project shape
  • choose
    stream_chat_flutter
    vs
    stream_chat_flutter_core
  • add Stream dependencies to
    pubspec.yaml
    and run
    flutter pub get
  • wire
    StreamChatClient
    and the
    StreamChat
    widget via
    sdk.md
  • complete platform setup (Android permissions, iOS Info.plist keys) for the chosen packages
  • stop before product-specific UI if the user only asked for setup

适用于用户更关注安装和接入路径而非功能构建的场景:
  • 检测项目形态
  • 选择
    stream_chat_flutter
    vs
    stream_chat_flutter_core
  • 将Stream依赖添加到
    pubspec.yaml
    并运行
    flutter pub get
  • 通过
    sdk.md
    接入
    StreamChatClient
    StreamChat
    组件
  • 为所选包完成平台设置(Android权限、iOS Info.plist键)
  • 如果用户仅要求配置,在产品特定UI开发前停止

Track M - Migrate from Sendbird

M跟踪路径 - 从Sendbird迁移

Full detail:
sendbird-migration.md
. Migration is integration-shaped (preserve the existing app), so it behaves like Track B with a Sendbird-specific runbook.
PhaseNameWhat you do
M1DetectRun Project signals; grep the Sendbird footprint and classify each touchpoint's shape (
sendbird-migration.md
§0). Capture the Sendbird baseline (§0.5 habit 0) — run the source app and screenshot every Sendbird-backed screen/variant (§0's touchpoints, not the whole app), list and chat, incoming and outgoing — before any code changes; those shots are the spec.
M2Swap + wireRemove
sendbird_chat_sdk
/
sendbird_uikit
, add Stream packages; get credentials (Step 0.5); wire one
StreamChatClient
+
StreamChat
provider, repointing existing bootstraps without changing their public API (§1–§2).
M3Re-implementMigrate each touchpoint per its pattern — views + navigation (§3), channels (§4), messages/custom attachments (§5); re-apply theming via the two axes (§6,
design-matching.md
).
M4VerifyCompare every region against the baseline and drive every interaction (§0.5 habits 2–3 +
design-matching.md
Step 5) — the exit is this comparison, not a green build.
Each region checked against its baseline shot at native scale (preserve path: zero visual change); the interactions the source actually has (reply/edit → composer, pickers, long-press, reactions, threads) performed on the device — a screen that paints can still be behaviorally dead. Anything unmatched is reported with its specific blocker (a named, grounded missing SDK API), never shipped silently at the Stream default. Confirm Sendbird deps are fully removed.
M5Offer dataOnce the code migration builds, connects, and matches, ask whether to also migrate the Sendbird data and hand off to
../stream/sendbird-data-migration.md
(§10).
详细信息:
sendbird-migration.md
。迁移属于集成形态(保留现有应用),因此行为类似于带有Sendbird特定手册的B跟踪路径。
阶段名称操作内容
M1检测运行项目信号检测;查找Sendbird痕迹并分类每个接触点的形态(
sendbird-migration.md
§0)。捕获Sendbird基准(§0.5习惯0)—— 在任何代码更改前运行源应用并截图每个Sendbird支持的屏幕/变体(§0中的接触点,而非整个应用),列表和聊天, incoming和outgoing —— 这些截图是规格。
M2替换+接入移除
sendbird_chat_sdk
/
sendbird_uikit
,添加Stream包;获取凭证(步骤0.5);接入一个
StreamChatClient
+
StreamChat
提供者,重新指向现有初始化代码而不更改其公共API(§1–§2)。
M3重新实现按形态迁移每个接触点—— 视图+导航(§3)、频道(§4)、消息/自定义附件(§5);通过两个维度重新应用主题定制(§6,
design-matching.md
)。
M4验证逐区域与基准对比并执行所有交互(§0.5习惯2–3 +
design-matching.md
步骤5)—— 完成标志是此对比,而非构建成功。
每个区域在原生缩放级别与基准截图对比(保留路径:零视觉变化);在设备上执行源应用实际具备的交互(回复/编辑→编辑器、选择器、长按、reactions、线程)—— 能渲染的屏幕仍可能存在行为失效。任何不匹配的内容需报告具体阻塞问题(命名的、有依据的缺失SDK API),切勿以Stream默认值静默交付。确认Sendbird依赖已完全移除。
M5提供数据迁移选项代码迁移构建成功、连接正常且匹配后,询问用户是否同时迁移Sendbird 数据,并移交至
../stream/sendbird-data-migration.md
(§10)。