Skip to content
Automation
Skill

/verify

How to verify media.sh changes end-to-end on a real Mac — isolated data dir, real native build, and a controllable fake now-playing app (no dependency on the user's music apps).

From plugin
media
416 skills1 hook

Claude Code

$ npx -y skills add Bangs00/claude-media-control --skill verify --agent claude-code

SKILL.md

verify.SKILL.md
name: verify
description: How to verify media.sh changes end-to-end on a real Mac — isolated data dir, real native build, and a controllable fake now-playing app (no dependency on the user's music apps).

Verifying claude-media-control

Surface = the `scripts/media.sh` CLI + the statusline segment it prints. `npx bats tests/media.bats` covers logic with stubs; real verification runs the actual pipeline (perl loader → adapter.dylib → mediaremoted).

Isolate from the user's live install

Always export a scratch data dir first — without it, `media.sh` falls back to `~/.claude/plugins/data/media-*` and mutates the user's real config/cache:

export CLAUDE_PLUGIN_DATA=/tmp/media-verify-data
scripts/build-native.sh --rebuild   # real dylib for this checkout's version

Publish a controllable now-playing track

Don't drive Music.app via AppleScript (`tell app "Music" to …` hangs on the Automation-consent dialog in headless contexts, and you can't control track titles). Instead compile a tiny publisher: MPNowPlayingInfoCenter + MPRemoteCommandCenter handlers + a silent AVAudioEngine source node (`clang -fobjc-arc -framework Foundation -framework MediaPlayer -framework AVFoundation npub.m -o npub`). Publish any title/artist/duration you need (long titles for marquee, CJK for width handling).

Two gotchas:

  • `appName`/`bundleIdentifier` only appear when the publisher runs from a

real `.app` bundle **launched via `open`** (LaunchServices registration); a bare executable publishes metadata but no app identity.

  • Kill it with `pkill -f <name>`; `media.sh now` must return `null` after.

What to drive

  • `media.sh now` — JSON incl. `outputDevice`, `appName`
  • `media.sh statusline` after `config display.statusline on` — run twice with

`sleep 2` between to see the marquee advance; `NO_COLOR=1` and `statusline.multiline on` are cheap probes

  • Statusline **wiring** (`statusline install/uninstall/status`, the

auto-wire in `config display.statusline on`, and the wrapper's uninstall self-heal) writes to `$HOME/.claude/settings.json` — export a scratch `HOME` too before driving it, or you will rewire the user's real settings. Simulate "plugin uninstalled" for the self-heal by emptying `$HOME/.claude/plugins/installed_plugins.json` (`{"plugins":{}}`) and making the recorded dev root non-executable/absent; the wrapper must restore `settings.json` and delete itself + the backup.

  • `media.sh output` / `output "<substring>"` / `output <n>` — switch to the

CURRENT device for a safe no-op, or switch away and back; `output "LG"` style ambiguous names must exit 4 with candidates

  • `media.sh history` / `history --json` — entries appear only on track

change (dedup across statusline ticks); drive an artist-lag amend by changing the published title first, then the artist one read later — the transitional entry must be replaced, not kept

  • **cmd+click round-trip** — `build-click-handler.sh` in the scratch data

dir, then `open "claude-media-control://seek/50"` etc. and assert on the fake publisher's command log. (The legacy `claude-media://` scheme is also claimed and accepted, but the user's REAL install claims it too — `open` routing for it is ambiguous on this machine, so exercise legacy URLs by calling the scratch `click-handler.sh` directly instead of via `open`.) Two gotchas: LaunchServices launches the applet WITHOUT `CLAUDE_PLUGIN_DATA`, so rewrite the scratch `click-handler.sh` to export it (and to exec THIS checkout's `media.sh` — the resolution block prefers the marketplace cache, which may hold an older version without `open-url`). Always `build-click-handler.sh --remove` afterwards to unregister the scheme, and delete any npub entries that the user's REAL statusline (ticking every second against the real data dir) logged while the fake publisher held now-playing

  • `media.sh doctor` — check the `Output dev` line and `verdict:`

`cat` may be aliased to `bat` in the user's shell — use `/bin/cat -v` to show SGR codes.

Restore

Volume, default output device, and any launched apps must match the pre-test state; the statusline cache lives in the scratch dir and dies with it.

Read more
@bangs00
Ships withmedia

The current track, live in your Claude Code statusline — ticking every second, ⌘+clickable, styleable down to the bar characters: And whatever your Mac is playing — Spotify, Apple Music, a browser tab, VLC — you can control it from the chat too: "what song is

Stars on GitHub

Momentum

stars in total
4
Star history of Bangs00/claude-media-control on GitHub, a chart by star-history.com

Other skills on media.

artwork

artwork

Show the album artwork (cover art) of the currently playing track. Use when the user asks to see the album art, cover image, or…

@bangs00@bangs00Install Skill
config

config

Quick media settings — turn the now-playing statusline, the /media:now progress bar, or the playback history on/off, or reset the…

@bangs00@bangs00Install Skill
doctor

doctor

Diagnose the media plugin — native build, read/control paths, fallbacks, permissions — and suggest fixes. Use when media commands…

@bangs00@bangs00Install Skill
history

history

Show recently played tracks (a passive local playback log). Use when the user asks what played earlier, what song was on before,…

@bangs00@bangs00Install Skill
menu

menu

Interactive media remote — control playback via a selectable menu (toggle, next, previous, seek, volume, artwork). Use when the…

@bangs00@bangs00Install Skill
next

next

Skip to the next track in whatever app is playing on this Mac. Use when the user says next song, skip this track, or change the…

@bangs00@bangs00Install Skill

More skills from other plugins.

agent-builder

agent-builder

Load immediately after an Agent intent, before the first agent_builder_* call. Governs how you create, configure, test, and…

n8n10d209k
@n8n-io@n8n-ioInstall Skill
browser-use

browser-use

Direct browser control via CDP for web interaction: automation, scraping, testing, screenshots, and site/app work. Also covers…

browser-usetoday120k
@browser-use@browser-useInstall Skill
agent-browser

agent-browser

Browser automation CLI for AI agents. Use when the user needs to interact with websites, including navigating pages, filling…

@vercel-labs-2@vercel-labs-2Install Skill
add-anydoc

add-anydoc

Add local office-document-to-Markdown conversion to NanoClaw agent containers with the pinned Firecrawl AnyDoc CLI. Use when…

@nanocoai@nanocoaiInstall Skill

Questions about verify.

Which coding agents can use verify?
verify installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.