Skip to content
Agentmart
Submit a tool

stream-feeds-migration

Generate the v2 -> v3 sync mapping for a Stream Activity Feeds app by sampling its live v2 activities and reactions and, when the app's v2 integration code is…

Skill by GetStream

IndexedApache-2.0★ 20
Write a review

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/getstream-stream-feeds-migration

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

Generate the v2 -> v3 sync mapping for a Stream Activity Feeds app by sampling its live v2 activities and reactions and, when the app's v2 integration code is available, reading its write paths, and, from that code, plan how the app's code moves from v2 to v3. Use when setting up a Feeds v2 to v3 migration, when asked to build, review, or debug a v3 sync mapping, when someone asks 'what mapping do we need for our app?', when asked how to port an app's v2 Feeds code to v3, or when a migrated activity lands in v3 with missing text, missing attachments, comments that are not comments, or bookmarks that went missing. Triggers on v3sync, v2 to v3, feeds migration, activity feeds migration, sync mapping, extra_context, reaction kinds, comments and bookmarks mapping, porting plan. The same mapping drives both the live syncer and the bulk exporter.

Use cases: writing

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md and code. Checked Oct 25, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found
Runs as
Python package

Network hosts it talks to 2

  • api.stream-io-api.com · found in code
  • codeload.github.com · found in install command

Files it touches

  • ~/.claude/skills/stream-feeds-migration

Tools it pre-approves 10

From allowed-tools in SKILL.md: the agent may use these without asking you each time.

  • Read,
  • Glob,
  • Grep,
  • Bash(python3
  • *),
  • Bash(ls
  • Bash(git
  • log
  • Bash(getstream
  • *)

What's inside

Skill name
stream-feeds-migration
Description
Generate the v2 -> v3 sync mapping for a Stream Activity Feeds app by sampling its live v2 activities and reactions and, when the app's v2 integration code is available, reading its write paths, and, from that code, plan how the app's code moves from v2 to v3. Use when setting up a Feeds v2 to v3 migration, when asked to build, review, or debug a v3 sync mapping, when someone asks 'what mapping do we need for our app?', when asked how to port an app's v2 Feeds code to v3, or when a migrated activity lands in v3 with missing text, missing attachments, comments that are not comments, or bookmarks that went missing. Triggers on v3sync, v2 to v3, feeds migration, activity feeds migration, sync mapping, extra_context, reaction kinds, comments and bookmarks mapping, porting plan. The same mapping drives both the live syncer and the bulk exporter.
License
Apache-2.0
Compatibility
Requires the v2 app's API key and secret, exported as environment variables, plus Python 3 (standard library only - no pip install). Read-only against the v2 app; writes one sample file to the working directory. No project or SDK required; when the app's repository is available, its v2 integration code is read to cover what a sample cannot and to write a porting plan. The skill never modifies the code; porting it is a follow-up done only when the user asks.
Allowed tools
Read,, Glob,, Grep,, Bash(python3, *),, Bash(ls, *),, Bash(git, log, *),, Bash(getstream, *)
Metadata
author: GetStream
Instructions
391 lines in SKILL.md · view on GitHub

Before installing

  • Ships executable scripts
  • Pre-approves some shell commands

Files (6)

  • SKILL.md
  • code-inventory.md
  • fetch_sample.py
  • mapping-keys.md
  • porting-plan.md
  • scan_v2_calls.py

SKILL.md (first lines)

# Stream Feeds - v2 to v3 sync mapping

For CLI commands or routing to another Stream skill, read
[`../stream/SKILL.md`](../stream/SKILL.md).

Produce the `mapping` object for an app's v2 -> v3 sync configuration by looking
at what the app's v2 data actually contains, rather than at what anyone believes
it contains.

One mapping serves both migration paths - the live syncer and the bulk exporter
read the same configuration. Getting it right once fixes both; getting it wrong
breaks both in the same way.

---

## Workflow

### 1. Get credentials into the environment

Use `getstream env` to write the **v2 app's** credentials to an env file. Read
`getstream env -h` for app selection and output options. Use `--target web` so
the file contains both `STREAM_API_KEY` and `STREAM_API_SECRET`, which the
sampler expects.

Load that file when running the sampler below. Do not print its contents or put
credential values in chat or tool commands.

### 2. Pick the target

**Default to production** - `https://api.stream-io-api.com`. Use it unless the
user names a different environment (EU, dedicated, staging), in which case pass
`--base-url <that URL>`.

Do not raise alternative environments on your own; production is the assumed
target and the user will say so if they mean otherwise.

### 3. Fetch the sample

```bash
set -a
. "<env-file>"
set +a
python3 <skill-dir>/fetch_sample.py --out v3sync-sample.json
```

`<env-file>` is the absolute path to the file written by `getstream env`. Run
the block in one shell invocation so Python inherits the credentials.

`<skill-dir>` is the directory holding this `SKILL.md`. Resolve it to an
absolute path before running - the skill runs from whatever directory the user
happens to be in, so a relative path only works by accident. `getstream skills`
links the pack into one of two places, so it is one of:

- `.agents/skills/stream-feeds-migration` (Cursor, Codex)
- `.claude/skills/stream-feeds-migration` (Claude Code)

Glob `{.agents,.claude}/skills/stream-feeds-migration/SKILL.md` to settle which.

The key and secret are read from `STREAM_API_KEY` and `STREAM_API_SECRET`. The
script takes **no `--secret` flag** by design - a secret passed as an argument
would land in the process list and the shell history, which is exactly what the
environment variable avoids. (`--api-key` exists, since the key is not
sensitive.) The sample is written to the working directory, which is where you
want it.

Standard library only - no pip install. It calls two server-side-only endpoints:

- `GET /api/v1.0/migration/sample/activities` - up to 100 activities, drawn
  from several periods (the newest, then at or before 7d, 30d, 180d, 1y and
  2y ago)
- `GET /api/v1.0/migration/sample/reactions` - 5 reactions per distinct kind

Both return **raw** stored payloads: unflattened `extra_context`, unmodified
reaction `data`. That is the point - you are looking for the real field names
and nesting.

A 401 or 403 means the secret is wrong, or the token was built as a user token
rather than a server-side one. A 404 means these endpoints are not available on
the app's deployment yet; [Stream support](https://getstream.io/contact/) can
confirm.

An empty `activities` array alongside a `200` is worth calling out rather than
working around: the app is either genuinely empty or its activity store cannot
serve this scan. Reactions carry an `activity_id`, so reactions in the sample
prove activities exist and point to the second explanation.

#### Read what the activity sample left out

Recent deployments also return `reaction_reference_count`,
`reaction_references` and `slices`, and the script keeps them in the sample
file. Read them before the activities, because they say how representative the
activities are:

- **`reaction_reference_count`** - how many target-feed copies of reactions
  the sample left out. v2 writes one of these when a reaction has
  `target_feeds`. You can recognise them by a `foreign_id` of `reaction:<id>`
  and an `extra_context.reaction` holding an `SR:` ref. They carry no post
  fields, so they say nothing about the mapping; up to 3 are in
  `reaction_references` for reference.
- **`slices`** - one entry per period, with `scanned`, `posts` and
  `reaction_references`. `before` is the period's cutoff; the newest slice has
  none. `extended` means the period was re-read with a larger scan because
  reaction references crowded it.
  - A slice whose `posts` is small next to `scanned` was crowded: posts from
    that period are under-represented. Say so.
  - A slice with `scanned: 0` held no activities **inserted** in that window.
    Periods are by insert time, not by the activity's `time`, so data imported
    into v2 recently all lands in the newest slice.

When the older slices are empty on an app that has existed for a while, the
sample cannot show what older posts look like. Ask whether the post format ever
changed (different field names for text, media or ids), and say the mapping only
covers the shape the sample shows.

If these keys are missing, the deployment predates them: the activities are the
newest 100 and can include reaction references. Leave those out yourself by the
shape above before analysing.

#### Cover every feed group

From GetStream/agent-skills, Apache-2.0.

More from GetStream/agent-skills

Signals

Stars
20
Forks
4
Open issues
0
Last commit (this folder)
Oct 22, 2026 (6 days ago)

From GitHub (fetched Oct 24, 2026).

Details

License
Apache-2.0
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from GetStream

Cite this page

stream-feeds-migration skill. Agent Mart. https://agentmart.dev/skills/getstream-stream-feeds-migration (last updated 2026-10-24)