John KuehJohn Kueh
All skills

Claude Code skill

claude-fm

Toggle lo-fi straight in the terminal — one command, no browser tab.

Add the marketplace once, then install this skill:

claude plugin marketplace add johnkueh/claude-skills
claude plugin install claude-fm@johnkueh-skills

Or grab the whole collection: claude plugin install claude-skills@johnkueh-skills

Hear it

The default station — what /music plays with no argument.

Why it exists

I like background music on a long session, but a YouTube tab is the wrong way to get it — it eats RAM, autoplays the next thing, and steals focus the moment a notification lands. This is a single toggle instead: it streams the audio with yt-dlp and plays it headless through ffplay, no window and no tab. Run it once and lo-fi starts; run it again and it stops. Pass any YouTube URL to change the station. It started as the /music command I keep wired into my own setup while shipping things like journeys.im and glp3.wiki — this is that, packaged so anyone can drop it in.

In practice

Start the default station
Input
/music
Output
▶ ✨ Claude FM playing — lo-fi, headless, no browser tab.
Toggle it back off
Input
/music
Output
⏹ Claude FM stopped.
Pick a different stream
Input
/music https://www.youtube.com/watch?v=<id>
Output
Plays that URL instead. ffplay runs with -nodisp, so a video link just gives you its audio.
skills/claude-fm/SKILL.mdRaw
---
name: claude-fm
description: Toggle Claude FM — a single command that starts or stops background YouTube audio (lo-fi by default) playing straight in the terminal while you work. Use when the user says "play music", "claude fm", "start the music", "lofi", "stop the music", "background music", or "/music". One call toggles: plays if silent, stops if already playing.
---

# claude-fm

A toggle for background audio in the terminal. Run it once and lo-fi (or any
YouTube URL) starts playing; run it again and it stops. No window, no tab — the
audio is streamed by `yt-dlp` and played headless by `ffplay`.

This is a deliberate one-line tool: the user hits it, gets a single status line
back, and keeps working. Don't add commentary beyond the script's output.

## How to run it

The toggle script ships next to this file. Run it and report **only** the line
it prints:

```bash
"${CLAUDE_PLUGIN_ROOT}/skills/claude-fm/music-toggle.sh"
```

- No argument → toggles the default station (lo-fi).
- A YouTube URL argument → starts that URL instead (only when nothing is
  playing; if audio is already playing, any call just stops it).

```bash
# Start a specific stream
"${CLAUDE_PLUGIN_ROOT}/skills/claude-fm/music-toggle.sh" "https://www.youtube.com/watch?v=<id>"
```

If `${CLAUDE_PLUGIN_ROOT}` isn't set in your environment, run the
`music-toggle.sh` that sits in this skill's own directory.

## Output lines

The script prints exactly one of:

- `▶  ✨ Claude FM playing` — started
- `⏹  Claude FM stopped` — stopped
- `⚠  Claude FM needs: …` — a dependency is missing (see Setup)
- `⚠  Couldn't start playback…` — bad URL / no playable format

Relay that line verbatim. Nothing else is needed.

## Setup

Two CLI tools must be on PATH:

```bash
brew install yt-dlp ffmpeg
```

`yt-dlp` pulls the audio stream; `ffmpeg` provides `ffplay`, which plays it
headless (`-nodisp`). The script preflight-checks both and tells the user the
exact `brew` line if either is missing — so you don't need to check first, just
run it and relay the message.

## Optional: a "now playing" statusline indicator

The toggle already confirms start/stop, so this is purely a persistent reminder.
Claude Code allows only **one** statusline command, so this isn't bundled — it
would clobber whatever statusline the user already has. If they want the
indicator, add this one line to their own `statusline.sh` (a `pgrep` on the
player process):

```bash
# Shows "✨ Claude FM" only while audio is playing
pgrep -x ffplay >/dev/null 2>&1 && printf ' | ✨ Claude FM'
```