Stream — skill router + execution flow
Rules: Read
once per session — every non-negotiable rule is stated there, nowhere else.
This file is the single entrypoint: intent classification, conditional context detection, and module pointers.
Step 0: Intent classifier (mandatory first — never skip)
Before any tool call, decide the track from the user's input alone — no probes, no fetches, no CLI checks. The classifier is deterministic: scan the input for the signals below in order.
Signals → track
| Signal in user input | Track | Skip CLI gate? |
|---|
| Explicit SDK/framework token: , , , , etc. (with or without version) | D — Docs search | Yes |
| Words "docs" or "documentation" | D | Yes |
| "How do I {X} in {framework}?", "How does {hook/component/method} work?", "What does {SDK thing} do?" | D | Yes |
| Operational verbs + Stream noun: "list calls", "show channels", "any flagged", "find users", "check {anything}" | B — CLI / data query | No |
| , , (literal CLI invocation) | B | No |
| "Build me a … app", "scaffold", "create a new …" + Stream product, in an empty/new directory | A — Builder (new app) | No |
| "Add Chat/Video/Feeds to this app", "integrate Stream into" — existing project | E — Builder (enhance) | No |
| "Install the CLI", "set up stream" with no project context | C — Bootstrap | n/a |
| Operational verb wrapped in how-to phrasing (e.g. "how do I list my calls?" — docs or CLI) | Ask one disambiguator | Defer |
Disambiguation flow
If the input fits more than one row (typically operational verb + how-to phrasing), ask one short question and wait. Do not probe, fetch, or gate before the answer.
Want me to look up the SDK method (docs) or run it now via CLI?
After the answer arrives, route as if the user had given that signal directly.
After classification
- Always (first invocation in conversation) → run Project signals. Cheap local probe; populates session context for every track.
- Track D → skip the CLI gate and CLI + credentials probes. Consume project signals, then go to .
- Tracks A, B, C, E → run the CLI gate then CLI + credentials, then the track. Project signals inform the one-line status and routing.
- Bare with no args → list the available tracks briefly and wait for input.
Project signals (always — once per session)
A local-only probe. No CLI binary, no network, no gate. Both Track D and tracks A/B/C/E consume the result, so it's worth running once on the first invocation regardless of which track was picked.
bash
bash -c 'echo "=== PKG ==="; grep -oE "\"(stream-chat[^\"]*|@stream-io/[^\"]*)\": *\"[^\"]*\"" package.json 2>/dev/null; echo "=== NEXT ==="; test -f package.json && grep -q "\"next\"" package.json && echo "NEXTJS" || echo "NO_NEXT"; echo "=== NATIVE ==="; ls pubspec.yaml go.mod requirements.txt pyproject.toml Podfile build.gradle 2>/dev/null; echo "=== EMPTY ==="; test -z "$(ls -A 2>/dev/null)" && echo "EMPTY_CWD" || echo "NON_EMPTY"'
Do NOT use (
= exit-on-error):
returns exit 1 when it finds no matches, which aborts the entire probe and leaves you with partial output. Same applies to every other probe in this file.
This gives you:
- PKG: Stream npm packages with versions (e.g.
"stream-chat-react": "^14.2.0"
) — empty if none
- NEXT: if is in , else
- NATIVE: Names of non-npm project files present (Flutter, Go, Python, iOS, Android)
- EMPTY: if cwd is empty, else
Hold the result in conversation context. Don't re-run unless:
- A scaffold (Track A) or install (Track E) completed and added new packages
- The user changed directory mid-conversation
- A signal you need is missing (e.g., Track D needs a version and was empty earlier — re-probe one specific file)
Don't print this result as a heading. Use it internally; surface a signal only when it changes what you say to the user (e.g., "I see Chat React v14 — looking up v14 docs.").
CLI gate (tracks A, B, C, E only)
Track D skips this step. For all other tracks: verify the
executable is installed and runnable before any further work.
- Run:
bash
bash -c 'command -v stream >/dev/null 2>&1 && stream --version || echo "NOT_FOUND"'
- If the output is or either command fails: stop here. Do not proceed to the credentials probe, builder, , credential checks, or SDK wiring. Follow (explain what the CLI is, ask the user once for permission to install, then run the install — needs network approval). Do not suggest continuing scaffold/CLI work without the binary; only after the user declines install may you offer read-only help from per bootstrap, or hand the user back to Track D for documentation questions.
- If succeeds: continue to the credentials probe.
CLI + credentials probe (tracks A, B, C, E only)
Run this single probe to confirm the CLI works and credentials are available. Project signals are already in context from the earlier local probe — don't repeat them here.
bash
bash -c 'echo "=== CLI ==="; command -v stream 2>/dev/null; stream --version 2>/dev/null || echo "NOT_FOUND"; echo "=== CONFIG ==="; stream config list 2>/dev/null || echo "NO_CONFIG"'
This gives you:
- CLI state: installed or not (should already be OK after the CLI gate)
- Config state: CLI configured () or not ()
is intentionally NOT checked here. Many sandbox configs install a
hook that blocks any bash command referencing
— including inside a
wrapper — which would silently fail this whole probe. For tracks A (new app) and E (enhance), you'll either create a fresh
via
(Task B) or work in a project that already has one; the project-signals probe tells you whether you're in an existing project.
Auth check (run only on tracks A/B/E that need to make calls):
The probe above does NOT verify you're logged in —
succeeds even when unauthenticated. Run one auth-requiring call,
unpiped so the exit code surfaces:
bash
stream api OrganizationRead
Do not pipe through
/
/
on this probe — the pipeline exit code is the last command's, which masks the auth failure. If output volume is a concern, redirect:
stream api OrganizationRead >/dev/null 2>&1; echo "exit=$?"
.
- Exit 0 → authenticated, continue. (Bonus: the output is reusable for Step 2's "check existing orgs".)
- Exit 2 / "not authenticated" → immediately run as its own Bash invocation (required for browser PKCE — never chain with or wrap inside a heredoc). Do not ask the user first.
- If hangs past ~60s or the user reports a stuck browser state → run to clear stale state, then retry once. If the second attempt also hangs, stop and ask the user to complete login manually (they can type to run it in-session).
Show a one-line status combining project signals and CLI + credentials:
✓ Stream CLI v0.1.0 · app-a3f7b201 (Feeds + Chat) · Next.js + Chat React v14 · ~/stream-tv
✓ Stream CLI v0.1.0 · configured via CLI · no local project
✓ Stream CLI v0.1.0 · no credentials · empty dir (ready to scaffold)
✗ Stream CLI not found — see bootstrap.md to install
(only if the CLI gate was skipped in error — do not route onward; go back and run it)
Install
Skill pack: npx skills add GetStream/agent-skills
(
skills.sh) — markdown only, does
not install the
binary.
CLI: See
for binary install from
/
.
Module map
Step 0 picks the track. Each Track section below has the full prerequisites and phase table — this is just the at-a-glance map.
| Track | Module(s) |
|---|
| A — Build new app | + |
| B — CLI / data query | ; tricky bodies → |
| C — Bootstrap | |
| D — Docs search (no CLI gate) | |
| E — Enhance existing app | (skip scaffold) + |
| SDK wiring inside A/E | + relevant |
Reference blueprints (load only after the user names the product, used by Tracks A and E):
| Product | Header (setup + gotchas) | Full blueprints (load per component) |
|---|
| Chat | | references/CHAT-blueprints.md
|
| Feeds | | references/FEEDS-blueprints.md
|
| Video | | references/VIDEO-blueprints.md
|
| Moderation | | references/MODERATION-blueprints.md
|
Cross-track follow-ups (use judgment)
The tracks share a single skill so a result from one can naturally enable an action in another. Surface a follow-up offer when it genuinely helps the user — not as boilerplate on every turn.
- D → B: A docs answer that names a runnable operation can offer "want me to run that now via CLI?" (only if read-safe or clearly operational intent).
- B → D: A CLI result that has a relevant docs page can offer "want the page that explains this?" (link only — don't fetch unprompted).
- A/E → D: After scaffold or integration completes, mention that the SDK + version is preloaded and ask-anything is available.
- D → A/E: A docs answer that describes a setup-heavy flow can mention scaffold / integrate is available — without running it.
Do not auto-execute a cross-track action. Offer, then wait for the user to confirm. The track switch happens through the user's reply, which re-enters Step 0.
Track A — Build new app (empty directory)
Full detail: Steps 0–7 in
; Step 4 UI in
.
| Phase | Name | What you do |
|---|
| A1 | CLI gate + context probe | Run the CLI gate then CLI + credentials. Show one-line status. If CLI missing, install via before A2 — never skip. |
| A2 | Execute | Immediately start Steps 0–7. Frontend skills + Shadcn/ui are always installed during Step 3 — no prompt needed. |
Anti-patterns: running skills install before scaffold; building a moderation review queue in the app.
Track B — CLI / data queries
Prerequisite: Complete the
CLI gate — the
CLI must be installed before running queries or credential resolution.
Credential resolution (do this before any
call):
- in cwd has → credentials are local. Mention which app you're querying if you can determine it.
- No → check for configured org/app → use those. Mention: "Querying configured app: ."
- Nothing → tell the user: "No Stream credentials found. Run to connect, or into a project with a ."
| Phase | Name | What you do | WAIT? |
|---|
| B1 | Resolve credentials | Run credential resolution above — silently if or config exists | Only if no credentials found |
| B2 | Execute | first; exit 5 → explain, confirm, retry without | — |
Track C — Bootstrap (install CLI / skill)
| Phase | Name | What you do | WAIT? |
|---|
| C1 | Explain | What is; one confirmation to install | User confirms |
| C2 | Install | Follow bootstrap (binary + npx skills add GetStream/agent-skills
) | As needed |
Track D — Docs search (no CLI gate)
The full docs-search engine: SDK identification (explicit input → project signals → keyword inference),
slug resolution, framework-index fetch, page fetch, cited answer. All honesty rules and URL-grounding rules live in
— read it before answering.
| Phase | Name | What you do |
|---|
| D1 | Identify SDK | Explicit input wins; otherwise consume project signals (PKG / NATIVE already in context); fall back to keyword tiers (Step 1c in ) |
| D2 | Resolve slug | Fetch once per conversation, find slug for product + framework |
| D3 | Fetch + answer | Fetch the framework index (verbatim URLs), pick the right page, fetch it, quote and cite |
Track D never invokes Write, Edit, npm, scaffold tools, or
. If the user asks for action mid-conversation, offer to switch tracks (D → B/A/E) and re-enter Step 0.
Track E — Enhance existing app
For adding Stream products to an existing Next.js project. Uses references files and SDK patterns but skips scaffold entirely.
Prerequisite: Complete the
CLI gate — install the
CLI before npm installs,
setup, or token routes that depend on CLI-backed config.
E1: Audit the existing project
Before writing any code, understand what's already in place:
- Packages: Check for , ,
@stream-io/video-react-sdk
, .
- Auth: Does the app already have a route? If so, extend it with the new product's token — don't create a second token route.
- Credentials: Check for with / . If missing, run credential resolution (Track B).
- UI framework: Confirm Tailwind, Shadcn, or whatever the project uses. Do not install Shadcn or change the styling setup unless the user asks.
- Directory structure: Note whether the project uses or — match the existing convention.
E2: Install + configure
- Install only the new SDKs:
npm install <new-packages> --legacy-peer-deps
(RULES.md › Package manager).
- Configure via CLI: run setup commands from the relevant (App Integration → Setup). For example, Feeds needs feed groups created; Moderation needs blocklist + config.
- Import CSS if the product needs it (Chat:
stream-chat-react/dist/css/v2/index.css
, Video: @stream-io/video-react-sdk/dist/css/styles.css
).
E3: Integrate
- Token route: Extend the existing to return the new product's token alongside existing ones. Follow for server-side instantiation patterns.
- API routes: Add product-specific routes from the relevant (App Integration → API Routes). Feeds needs several (, , etc.); Chat and Video typically only need the token route.
- Components: Load the relevant
references/<Product>-blueprints.md
sections and build components using the existing project's patterns and styling conventions — not the builder-ui.md defaults.
- State: If the app already manages user state (auth context, session), wire Stream tokens into that — don't add a separate Login Screen unless the app has no auth.
E4: Verify
Key constraints
- Do not re-scaffold, re-initialize Shadcn, install frontend skills, or modify / .
- Do not overwrite or restructure existing files — add new files alongside them.
- Do not change the existing auth flow. Adapt Stream's token generation to fit the app's existing auth, not the other way around.
- If the project uses a different package manager (yarn, pnpm), match what it already uses — the npm-only rule applies to new scaffolds, not existing projects.
Paths (portable)
| What | Where |
|---|
| Reference headers | agent-skills/skills/stream/references/*.md
|
| Reference blueprints | agent-skills/skills/stream/references/*-blueprints.md
|
| Docs search engine | agent-skills/skills/stream/docs-search.md
|
| CLI endpoint index | after |
| Skill modules | agent-skills/skills/stream/
|
Tooling (all hosts)
Loading: This file (
) +
+ files
named by the routing table for the task. Track D loads
only; tracks A/B/C/E load their respective modules.
Batching: One
per builder phase where possible (never
—
aborts on any non-zero exit, including
finding nothing).
stays its own invocation for browser PKCE — never chain with
or wrap in a heredoc.
Support: If the user asks for support or how to contact someone, direct them to
getstream.io/contact.