> multistream-manager

~ $ msm

Set up a Twitch stream and a YouTube broadcast from one form, then press Start Streaming in OBS.

msm is a terminal interface that configures a Twitch stream and a YouTube live broadcast from a single form, then shows the live figures for both platforms side by side. It never touches OBS, and your YouTube stream key stays exactly where it is.

The dashboard after a successful go-live: a Twitch panel and a YouTube panel side by side, each with its watch URL, its ingest URL, a masked stream key, and the live figures — viewers, uptime, followers, likes. The stream key is hidden until you press k.

the problem

If you stream to both platforms at once — for example through OBS with the Aitum multistream plugin — the routine before every session is the same:

  1. Open YouTube Studio. Create a live broadcast. Type the title and description, pick a category, set the visibility, tick “not made for kids”.
  2. Open the Twitch dashboard. Type the same title again, search for the category, retype the same tags, set the language.
  3. Find a stream key and get it into OBS or Aitum.
  4. Finally, press Start Streaming in OBS.

msm collapses steps 1 to 3 into one form. You type the title, description, tags, category and language once, press Ctrl+G, and both platforms are configured in parallel. Step 4 does not change: this tool never controls OBS.

install

The one-liner downloads the latest release binary and puts it on your PATH:

curl -fsSL https://raw.githubusercontent.com/worxbend/multistream-manager/main/install.sh | sh

Prebuilt binaries are Linux x86_64 and aarch64. On macOS and Windows, build from source with cargo install --path . — that needs Rust 1.88 or newer. Either way you end up with a binary called msm; run msm --help to check it.

what you get

  • One form, both platforms

    Title, description, tags, category and language are typed once and pushed to Twitch and YouTube at the same time.

  • Your YouTube key stays put

    Each new broadcast binds to a stream that already exists on your channel, so OBS and Aitum keep the key you gave them.

  • Both dashboards in one window

    Viewers, uptime and subscribers for both platforms; followers on Twitch, likes on YouTube, refreshed while you stream. Neither website needs to be open.

  • Partial success is normal

    If one platform fails, the other still goes ahead. The panels say which worked, which did not, and why.

  • Twitch categories, resolved

    The category field autocompletes as you type and turns the name into the numeric game id Twitch's API requires.

  • Scriptable when you want it

    Your config file doubles as an editable preset. msm go applies it without opening the interface; msm go --json prints one object per platform.

how it works

  1. Choose the platforms

    Tick Twitch, YouTube or both. Anything you do not tick is left alone, and each platform is logged in separately over a loopback OAuth flow with PKCE.

  2. Fill in one form

    Title, description, tags, category and language, plus the two settings only YouTube has: visibility, and whether it should go live by itself once it sees the feed.

  3. Press Ctrl+G

    Twitch has no separate “create broadcast” step, so its channel is updated in place. On YouTube a broadcast is created and bound to your existing stream, then tags, category and language are applied to the underlying video.

  4. Press Start Streaming in OBS

    Exactly as you always did, with Aitum sending the second copy to YouTube. msm reads statistics from both platforms from then on.

the stream key

Why your YouTube stream key never changes

This is the part that makes the whole thing work, so it is worth spelling out. YouTube's API keeps two separate objects: a broadcast is the event, with a title and a watch page; a stream is the RTMP pipe that carries the video, and it is the thing that holds the key.

Creating a new stream object mints a brand new key. A tool that created one per session would hand you a different key every time, and you would be pasting it into Aitum before every stream — the exact chore this is meant to remove.

So msm reuses a stream that is already on your channel and binds the new broadcast to that one. YouTube's list endpoint does not report whether a given stream can be reused, so msm binds the candidate and only falls back to creating a fresh stream if the bind is refused. When that happens it says so plainly, because a new key is the one thing you have to act on.

If your channel has several keys, msm streams lists them and stream_id in the config pins the one you want.

commands

Running msm with no arguments opens the interface, which is how it is meant to be used. The subcommands cover the things a terminal interface is bad at: one-off logins, scripted go-lives, and printing a key.

msm
Open the terminal interface. This is the default.
msm tui
The same thing, spelled out.
msm login <twitch|youtube|all>
Authorise a platform in your browser.
msm logout <twitch|youtube|all>
Forget a platform's saved login.
msm status
Show which platforms are logged in and where the config lives.
msm go [--platforms <LIST>] [-y|--yes] [--json]
Apply the preset from your config file without opening the interface. --json implies --yes and never prints the stream key.
msm key <twitch|youtube>
Print a platform's stream key, for pasting into OBS or Aitum.
msm categories <QUERY>
Search Twitch's category list from the command line.
msm streams [--show-keys]
List the stream keys on your YouTube channel, and which one is pinned.
msm cleanup [-y|--yes]
Find YouTube broadcasts that were created but never went live. Anything that ever received a feed is never listed and never deleted.
msm init
Write a commented starter config file.
msm paths
Show where the config, token and log files live.

-c, --config <FILE> works on every subcommand, so you can keep one preset per kind of stream.