Build and integrate Stream Chat, Video, and Feeds in Flutter apps. Use for Flutter/Dart project work with Stream package setup, auth wiring, and widget blueprints. Supports stream_chat_flutter (pre-built Chat UI), stream_chat_flutter_core (custom Chat UI), stream_video_flutter (Video calling and livestreaming), and stream_feed / stream_feed_flutter_core (Activity Feeds, no pre-built UI).
83
—
Does it follow best practices?
Impact
98%
1.81xAverage score across 2 eval scenarios
Risky
Do not use without reviewing
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.
Before any tool call, decide the track from the user's input alone - no probes first.
| Signal in user input | Track |
|---|---|
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 work | C - 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" + Stream | A - 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 request | D - Bootstrap / setup |
Bare /stream-flutter with no args | List the tracks briefly and wait |
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?
builder.md and sdk.md.Run this once per session, right after intent classification, before the Project signals probe.
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.
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:
- Credentials - Should I fetch your API key from the dashboard and generate a token via the Stream CLI, or will you paste them yourself?
- Token expiry - If I'm generating the token: should it expire? (e.g.
1h,1d,30m) or never expire?- 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:
- Credentials - Should I fetch your API key from the dashboard and generate a token via the Stream CLI, or will you paste them yourself?
- 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
guestrole, which by default has minimal capabilities. On thelivestreamcall type guests cannot even read or join a call until the integrator grants those capabilities to theguestrole. When a guest-based viewer flow is in scope, tell the integrator it is a prerequisite to grant theguestroleread-callandjoin-call(pluscreate-callif a viewer may open the call before the host) on the relevant call type via Stream Dashboard → Video & Audio → Call Types → → Roles & Permissions (or the API), or to use authenticatedUser.regularviewers instead. Details:references/VIDEO-FLUTTER.md→ Guest users, andreferences/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:
- Credentials - Should I fetch your API key from the dashboard and generate a token via the Stream CLI, or will you paste them yourself?
- Token expiry - If I'm generating the token: should it expire? (e.g.
1h,1d,30m) or never expire?- 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?
- 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":
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():
_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._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.
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?".
getstream env --target flutterThis 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.
# Never-expiring
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.
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):
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):
getstream api GetOrCreateChannel --type messaging --id <channel-id> \
--request '{"data": {"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.
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)
After all CLI steps succeed, move straight to Project signals and then into builder.md - no additional prompt needed. If any CLI step fails, explain the error briefly and ask the user to paste the missing value manually before continuing.
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 building | Grant the connecting role needs on the channel type | Default 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.
Read-only local probe. Use it to detect whether the user is in a Flutter project or an empty directory.
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.yamlFlutter app detected - stream_video_flutter already in pubspec.yamlFlutter app detected - stream_feed already in pubspec.yamlFlutter app detected - no Stream dependency yet, ready to installNo Flutter project found - user needs to run flutter create firstWhen 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_flutterv. 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.
| Track | Module(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 |
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").
Shared Flutter/Dart patterns live in sdk.md.
Product and package specifics live under references/ using a flat naming scheme:
references/<PRODUCT>-<PACKAGE>.mdreferences/<PRODUCT>-<PACKAGE>-blueprints.mdCurrent extracted modules:
stream_chat_flutter): references/CHAT-FLUTTER.md + references/CHAT-FLUTTER-blueprints.mdstream_chat_flutter_core): references/CHAT-CORE.md + references/CHAT-CORE-blueprints.mdreferences/CHAT-ADVANCED-FLUTTER.md + references/CHAT-ADVANCED-FLUTTER-blueprints.md - push notifications, offline/local persistence, connection lifecycle & backgroundingstream_video_flutter): references/VIDEO-FLUTTER.md + references/VIDEO-FLUTTER-blueprints.mdstream_video_flutter): references/LIVESTREAM-FLUTTER.md + references/LIVESTREAM-FLUTTER-blueprints.mdstream_video_flutter): references/VIDEO-ADVANCED-FLUTTER.md + references/VIDEO-ADVANCED-FLUTTER-blueprints.md - audio rooms, multicall, chat+video, livestream feed, querying/events/preferences/moderationstream_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)stream_feed / stream_feed_flutter_core): references/FEEDS-FLUTTER.md + references/FEEDS-FLUTTER-blueprints.mdAdditional Stream product coverage should stay in this naming family instead of creating more top-level skills.
Full detail: builder.md - use the new-project path.
| Phase | Name | What you do |
|---|---|---|
| A1 | Detect | Run Project signals. If there is no Flutter app yet, tell the user to run flutter create my_app first. |
| A2 | Choose lane | Confirm 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 Feeds, default to Twitter-style UI. |
| A3 | Install + wire | Follow builder.md + sdk.md, then load only the needed reference files. |
| A4 | Verify | Confirm 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. |
Full detail: builder.md - use the existing-project path.
| Phase | Name | What you do |
|---|---|---|
| B1 | Detect | Run Project signals and inspect the existing app structure before editing. |
| B2 | Preserve | Keep the current navigation, state management, and widget architecture unless the user asks for a change. |
| B3 | Integrate | Use sdk.md for shared wiring, then load only the needed reference files. |
| B4 | Verify | Confirm 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. |
Load only the relevant files for the requested package.
sdk.mdreferences/CHAT-ADVANCED-FLUTTER.mdreferences/CHAT-ADVANCED-FLUTTER-blueprints.mdreferences/CHAT-FLUTTER.mdreferences/CHAT-FLUTTER-blueprints.mdreferences/CHAT-CORE.mdreferences/CHAT-CORE-blueprints.mdreferences/VIDEO-FLUTTER.mdreferences/VIDEO-FLUTTER-blueprints.mdreferences/LIVESTREAM-FLUTTER.mdreferences/LIVESTREAM-FLUTTER-blueprints.mdreferences/VIDEO-ADVANCED-FLUTTER.mdreferences/VIDEO-ADVANCED-FLUTTER-blueprints.mdreferences/RINGING-FLUTTER.mdreferences/RINGING-FLUTTER-blueprints.mdreferences/FEEDS-FLUTTER.mdreferences/FEEDS-FLUTTER-blueprints.mdUse when the user wants the install and wiring path more than a feature build:
stream_chat_flutter vs stream_chat_flutter_corepubspec.yaml and run flutter pub getStreamChatClient and the StreamChat widget via sdk.mdb81d80e
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.