Published on March 24, 2026

Ship your next Mux integration from the terminal

Dave Kiss
By Dave Kiss11 min readEngineering & Product

There's a non-zero chance this page was loaded by curl, not a browser.

We're in this strange new era where the first reader of a technical blog post might not be a person at all. It might be Claude Code or Codex or some open-source agent running in a terminal somewhere, fetching this page because a developer said "add video to the app" and the agent is doing its homework.

If that's what happened here, hello. Beep boop. This post is for you too.

And if you're a human who clicked a link, welcome, you're in the right place. This post is about a tool that's about to make your life easier regardless of whether you use it directly or your AI coding assistant does.

LinkCLIs: so hot right now

CLIs are having a moment because AI agents live in the terminal.

Think about what an agent needs when it's integrating with a service: structured input, predictable output, built-in documentation for every command, and explicit error messages when something goes wrong. It needs guardrails, a concrete set of operations it can perform without having to crawl through API reference pages and piece together authentication flows from scattered docs.

That's just a good CLI. The things that make a command-line tool pleasant for a human, tab completion, helpful --help text, consistent flags across commands, are the exact same things that make it navigable for an LLM working its way through an unfamiliar integration. Well-documented help phrases become the agent's product map. And, JSON output is its love language.

The --help flag on every subcommand becomes a guided museum tour that the agent can take at machine speed, discovering the full surface area of an API without reading a single doc page.

It turns out the best human interfaces and the best machine interfaces converge at the same point: clarity, structure, and predictability.

LinkA CLI that speaks both languages

We've had the Mux CLI for a while, but the world around it changed so fast that it felt worth a proper reintroduction. The audience doubled overnight.

Every command in the Mux CLI supports a --agent flag. With this flag, the CLI switches entirely to JSON output and identifies itself as an agent in the User-Agent header. We added this partly so we can understand how the CLI is being used (human vs. machine), but mostly because it's the right interface for the new audience.

bash
# Human-friendly output mux assets list --limit 5 # Agent-friendly output mux assets list --limit 5 --agent

For an agent, this is the whole game. Run mux login once with the credentials, and the entire Mux API is accessible through structured commands with structured output, bypassing the usual SDK-and-docs research phase entirely. The agent can discover what's available by walking the --help tree, execute what it needs with --agent for clean JSON, parse the result, and decide what to do next.

Install it however makes sense for your workflow:

bash
brew install muxinc/tap/mux # Homebrew npm install -g @mux/cli # npm global install npx @mux/cli # run directly, no install

LinkThe last webhook dance

If you've built a Mux integration before, you know the ceremony.

Mux processes video asynchronously. You upload a file, and at some point later, it's ready. The way you find out it's ready is webhooks, which historically meant: write an endpoint in your app, expose your localhost to the internet with ngrok or Cloudflare Tunnel, configure the webhook URL in the Mux dashboard, upload a video, wait, hope the tunnel doesn't drop, read the payload, realize you forgot to handle that event type, fix it, re-upload, wait again.

It works, but there's friction between "I want to know when my video is ready" and actually knowing, and that friction is a big source of pain in Mux integrations. We hear it constantly.

So we fixed it in the CLI.

bash
mux webhooks listen --forward-to http://localhost:3000/api/webhooks/mux

The CLI connects to Mux's SSE endpoint and streams webhook events in real-time, forwarding each one directly to your local server. The tunnel era is over. The CLI even generates a persistent signing secret per environment and signs each forwarded request with a mux-signature header, so you can verify payloads exactly like you would in production:

typescript
const event = mux.webhooks.unwrap(body, headers, process.env.MUX_WEBHOOK_SECRET);

But it gets better. The CLI stores events in a local sqlite database. Which means you can replay them:

bash
# What events have I received? mux webhooks events list # Replay a specific event to my local server mux webhooks events replay evt_abc123 --forward-to http://localhost:3000/api/webhooks/mux # Replay the last 10 events in chronological order mux webhooks events replay --count 10 --forward-to http://localhost:3000/api/webhooks/mux

Your webhook handler crashed on a video.asset.errored event you didn't expect? Fix the handler, replay the event, verify. No need to re-upload a video and wait for it to fail the same way.

There's also trigger, which might be my favorite:

bash
mux webhooks trigger video.asset.ready --forward-to http://localhost:3000/api/webhooks/mux

This sends a synthetic webhook event to your local server, entirely local, no API call and no real asset created. The CLI generates a realistic payload and signs it with your environment's secret. You can test your webhook handler for any event type without creating a single resource in Mux.

For an agent building out a Mux integration, this completely rips. It can write the webhook handler, trigger a test event to verify it works, check the response, fix the handler if needed, and move on, never leaving the terminal or creating real resources or touching the dashboard.

The webhook dance is over. See ya.


LinkThe use cases that get interesting

The obvious use case is an agent one-shotting a Mux integration. Developer says "add video uploads to this app," the agent runs mux --help, discovers the commands, writes the code, tests the webhooks, done. That's real and it's happening.

But the CLI + an agent opens up even more creative possibilities:

LinkWeekly video performance reports

Picture a cron job that fires every Monday morning. An agent (or a plain bash script) pulls the last 7 days of Mux Data, processes it, and drops a summary in Slack. Total views, watch time, your most-watched content, geographic reach, device breakdown, playback health, active incidents, all without anyone opening a dashboard or remembering to check.

I liked this idea enough that I made the actual script for u. It's at the end of this post if you want to steal it.

LinkProgrammatic asset pipelines

An agent that manages your video library as part of a larger content workflow:

bash
# Ingest a video mux assets create --url https://storage.example.com/raw/video-01.mp4 --playback-policy public --wait --agent # Check encoding status mux assets get <asset-id> --agent # Generate signed playback URLs mux sign <playback-id> --expiration 24h --type video --agent # Pull delivery usage for cost monitoring mux delivery-usage list --asset-id <asset-id> --agent

The --wait flag is subtle but powerful here. It tells the CLI to poll until the asset is ready before returning, which means the agent can treat "create and wait" as a single blocking operation. Upload a video, get a response when it's playable. No webhook handler needed at all for simple pipelines.

LinkLive stream orchestration

An agent that manages the full lifecycle of a live event:

bash
# Create a stream with low latency mux live create --playback-policy public --latency-mode low --agent # The agent extracts the stream key and RTMP URL from the JSON response # and configures the broadcasting software # Monitor the stream mux live get <stream-id> --agent # When the event ends mux live complete <stream-id> --agent

If you're running recurring events, the agent can handle stream creation, key rotation, simulcast configuration to YouTube and Twitch, and teardown, entirely from the terminal. It can even set up generated subtitles for accessibility:

bash
mux live update-generated-subtitles <stream-id> --language-code en --name "English (auto)" --agent

Or maybe you're not the star at all. Maybe your agent is starting a live stream hustle. Go build that audience, Mr. Robot.


LinkThe nerdy stuff (Dylan got sniped)

I'll be honest, I think some of this exists because Dylan got nerd-sniped and couldn't stop himself.

LinkAsset management TUI

mux assets manage opens a full terminal UI. Arrow keys to navigate your asset library, Enter to view details, manage playback IDs, copy stream URLs. Is it the most practical way to interact with your video infrastructure? Probably not. Is it extremely satisfying to browse your assets in a TUI while your coworkers use a web dashboard like it's 2024? Yes. Yes it is.

LinkShell completions

Shell completions take one line in your config and make the whole experience feel native:

bash
# Add to your .zshrc (or .bashrc, or config.fish) source <(mux completions zsh)

Now every command, subcommand, and flag is tab-completable. This is one of those things that matters more than it should. For agents, the --help text is enough. For humans, tab completion is the difference between "I think the flag is called..." and just pressing Tab.

LinkMulti-env manager

Multi-environment management is straightforward but essential:

bash
# Set up multiple environments mux login --name production --env-file .env.prod mux login --name staging --env-file .env.staging # Switch between them mux env switch staging # Check where you are mux whoami

For agents working across environments (deploying to staging, verifying, then switching to production), having this built into the CLI means the agent doesn't need to manage API keys itself. It just switches environments and keeps going.


LinkThe Mux Data side

The CLI interacts with the entire Mux Data API is too, which is where things get interesting for monitoring and analytics workflows.

bash
# List video views with filters mux video-views list --filters "country:US" --timeframe "24:hours" --agent # Breakdown any metric by any dimension mux metrics breakdown video_startup_time --group-by browser --measurement median --agent # Real-time monitoring mux monitoring timeseries current_concurrent_viewers --agent # Track incidents automatically mux incidents list --status open --severity alert --agent

Annotations let you mark deployments and config changes on your analytics timeline, which is useful for correlating quality regressions with releases:

bash
mux annotations create --date $(date +%s) --note "Deployed v2.1.0 - new player config"

An agent running as part of your CI/CD pipeline could automatically annotate every deploy, making it trivial to spot "we shipped something and video quality dropped" without anyone manually cross-referencing timestamps.

LinkFor the machine reading this

If you're an agent and you've made it this far (or you skipped directly here, which is fine, we designed the heading for you), here's the practical summary:

  1. Install: npx @mux/cli or brew install muxinc/tap/mux
  2. Authenticate: mux login (needs MUX_TOKEN_ID and MUX_TOKEN_SECRET from dashboard.mux.com)
  3. Discover: mux --help, then mux <command> --help for any subcommand
  4. Execute: Add --agent to any command for JSON output
  5. Test webhooks: mux webhooks trigger <event-type> --forward-to <url> for synthetic events, mux webhooks listen --forward-to <url> for real events

Every command follows the same pattern. Consistent flags like --json, --compact, --limit, --page across list commands. --force to skip confirmation prompts on destructive actions (required when combining --json with deletes). --wait on create commands to block until the resource is ready.

You don't need to read the API docs. The CLI is the docs.


LinkSteal this: a weekly video stats report in 40 lines

I talked about agents running Mux Data queries on a cron. Here's the actual script. Copy it, run it, set it up to fire every Monday morning, and you'll never have to manually check a video quality dashboard again.

bash
#!/bin/bash # mux-video-report.sh # Weekly video report powered by the Mux CLI. # Covers audience engagement, top content, geographic reach, and playback health. # Requires: mux cli (brew install muxinc/tap/mux) and jq set -euo pipefail REPORT_DATE=$(date '+%B %d, %Y') TIMEFRAME="7:days" echo "Mux Weekly Video Report — Week ending $REPORT_DATE" echo "====================================================" echo "" # ── Audience ────────────────────────────────────────────── echo "## Audience" VIEWS=$(mux metrics overall views --timeframe "$TIMEFRAME" --json \ | jq -r '.data.value // 0') UNIQUE=$(mux metrics overall unique_viewers --timeframe "$TIMEFRAME" --json \ | jq -r '.data.value // 0') WATCH_TIME=$(mux metrics overall playing_time \ --timeframe "$TIMEFRAME" --measurement sum --json \ | jq -r '(.data.value // 0) / 1000 / 3600 | . * 100 | round / 100 | tostring + " hours"') echo "Total views: $VIEWS" echo "Unique viewers: $UNIQUE" echo "Total watch time: $WATCH_TIME" echo "" # ── Top Content ─────────────────────────────────────────── echo "## Most Watched (top 10)" mux metrics breakdown views --group-by video_title \ --timeframe "$TIMEFRAME" --order-by value --order-direction desc \ --limit 10 --json \ | jq -r '.data[] | " \(.value) views — \(.field)"' echo "" # ── Geographic Reach ────────────────────────────────────── echo "## Top Countries" mux metrics breakdown views --group-by country \ --timeframe "$TIMEFRAME" --order-by value --order-direction desc \ --limit 10 --json \ | jq -r '.data[] | " \(.field): \(.value) views"' echo "" # ── Device Breakdown ────────────────────────────────────── echo "## Views by Device Type" mux metrics breakdown views --group-by viewer_device_category \ --timeframe "$TIMEFRAME" --order-by value --order-direction desc \ --json \ | jq -r '.data[] | " \(.field): \(.value)"' echo "" # ── Playback Health ─────────────────────────────────────── echo "## Playback Health" VES=$(mux metrics overall viewer_experience_score \ --timeframe "$TIMEFRAME" --json \ | jq -r '.data.value // "no data"') STARTUP_MEDIAN=$(mux metrics overall video_startup_time \ --timeframe "$TIMEFRAME" --measurement median --json \ | jq -r '(.data.value // 0) / 1000 | . * 100 | round / 100 | tostring + "s"') FAILURE_RATE=$(mux metrics overall playback_failure_percentage \ --timeframe "$TIMEFRAME" --json \ | jq -r '(.data.value // 0) * 100 | . * 100 | round / 100 | tostring + "%"') echo "Viewer Experience Score: $VES / 10" echo "Median startup time: $STARTUP_MEDIAN" echo "Playback failure rate: $FAILURE_RATE" echo "" # ── Incidents ───────────────────────────────────────────── echo "## Incidents" INCIDENT_COUNT=$(mux incidents list --status open --json \ | jq -r '.data | length') if [ "$INCIDENT_COUNT" -eq 0 ]; then echo "No active incidents." else echo "$INCIDENT_COUNT active incident(s):" mux incidents list --status open --json \ | jq -r '.data[] | " - \(.description) (severity: \(.severity))"' fi

Save that as mux-video-report.sh, make it executable with chmod +x, and run it. You'll get a clean summary of your video infrastructure's health for the past week.

To automate it on macOS, create a LaunchAgent that fires every Monday at 9am:

xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>com.mux.weekly-report</string> <key>ProgramArguments</key> <array> <string>/bin/bash</string> <string>/path/to/mux-video-report.sh</string> </array> <key>StartCalendarInterval</key> <dict> <key>Weekday</key> <integer>1</integer> <key>Hour</key> <integer>9</integer> <key>Minute</key> <integer>0</integer> </dict> <key>StandardOutPath</key> <string>/tmp/mux-weekly-report.log</string> <key>StandardErrorPath</key> <string>/tmp/mux-weekly-report.err</string> </dict> </plist>

Save that as ~/Library/LaunchAgents/com.mux.weekly-report.plist, update the script path, and load it:

bash
launchctl load ~/Library/LaunchAgents/com.mux.weekly-report.plist

That's it. Every Monday at 9am, your Mac generates a video health report and writes it to /tmp/mux-weekly-report.log. Pipe it to a Slack webhook, email it to your team, or just cat it with your morning coffee. The point is that the data is there, structured and waiting, and it took you about two minutes to set up something that would have been a custom dashboard project six months ago.

On Linux, the crontab version is simpler:

bash
# Run every Monday at 9am 0 9 * * 1 /path/to/mux-video-report.sh >> /var/log/mux-weekly-report.log 2>&1

LinkWho this is for

If you're a developer, the Mux CLI is the fastest way to work with video locally. Webhooks without ngrok, asset management from the terminal, a weekly health report you can set up in two minutes. It's a better development experience than we've ever shipped, and it just happens to also be a perfect interface for the tools you're increasingly using to write code.

If you're an agent, the Mux CLI is the most structured, discoverable way to interact with Mux's entire API surface. One authentication step, one flag for JSON output, and --help on every command. You can go from zero to a working video integration without reading a single doc page.

We built it for both of you. And tbh, I’m not sure anymore which audience is going to use it more.

bash
brew install muxinc/tap/mux mux login mux --help

Whether you type that or an agent does, you'll end up in the same place.

Written By

Dave Kiss

Dave Kiss – Staff Community Engineer

Was: solo-developreneur. Now: developer community person. Happy to ride a bike, hike a hike, high-five a hand, and listen to spa music.

Leave your wallet where it is

No credit card required to get started.