{"id":51440774,"url":"https://github.com/lomartins/cadence","last_synced_at":"2026-07-05T11:30:46.620Z","repository":{"id":367366790,"uuid":"1280457824","full_name":"lomartins/cadence","owner":"lomartins","description":"🎧 Focus music for Claude Code — detects your current task and plays Spotify music matched to it, learning your taste over time. Auto-switches or on request.","archived":false,"fork":false,"pushed_at":"2026-06-25T18:09:12.000Z","size":305,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-25T18:21:34.519Z","etag":null,"topics":["claude-code","claude-code-plugin","deep-work","flow","focus-music","mcp","pomodoro","productivity","spotify","spotify-web-api"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lomartins.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-25T15:50:10.000Z","updated_at":"2026-06-25T18:09:17.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/lomartins/cadence","commit_stats":null,"previous_names":["lomartins/cadence"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/lomartins/cadence","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lomartins%2Fcadence","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lomartins%2Fcadence/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lomartins%2Fcadence/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lomartins%2Fcadence/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lomartins","download_url":"https://codeload.github.com/lomartins/cadence/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lomartins%2Fcadence/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35153107,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-05T02:00:06.290Z","response_time":100,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["claude-code","claude-code-plugin","deep-work","flow","focus-music","mcp","pomodoro","productivity","spotify","spotify-web-api"],"created_at":"2026-07-05T11:30:44.921Z","updated_at":"2026-07-05T11:30:46.598Z","avatar_url":"https://github.com/lomartins.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"assets/banner.svg\" alt=\"Cadence — focus music for Claude Code\" width=\"100%\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cb\u003eCadence\u003c/b\u003e detects what you're working on and plays Spotify music matched to the task — tuned to your taste, learned over time, to keep you in flow.\n  \u003cbr\u003e\u003cbr\u003e\n  \u003ca href=\"#install\"\u003e\u003cimg src=\"https://img.shields.io/badge/Claude_Code-plugin-7C5CFC?style=flat-square\" alt=\"Claude Code plugin\"\u003e\u003c/a\u003e\n  \u003cimg src=\"https://img.shields.io/badge/license-MIT-22D3A6?style=flat-square\" alt=\"MIT\"\u003e\n  \u003cimg src=\"https://img.shields.io/badge/Spotify-Web_API-1DB954?style=flat-square\" alt=\"Spotify Web API\"\u003e\n  \u003cimg src=\"https://img.shields.io/badge/node-%E2%89%A518-339933?style=flat-square\" alt=\"node \u003e= 18\"\u003e\n\u003c/p\u003e\n\n---\n\n## What it does\n\nYou code. Cadence quietly reads the *shape* of your work — debugging, writing docs,\nplanning, reviewing, crunching — and plays music chosen to suit it: lyric-free\ndeep-focus beats while you implement, warm steady jazztronica while you debug,\npeaceful piano while you write, driving DnB when you're shipping under pressure.\n\n- 🎚️ **Auto-switches** music as your task changes — or stays fully manual. Your call.\n- 🧠 **Learns your taste** per work mode from your feedback (love / like / dislike / ban / more-like-this) and your listening — all **100% local**.\n- 🎯 **9 curated vibes** mapped to work modes, each grounded in focus/attention research.\n- 🔌 **Spotify Web API** (OAuth PKCE) with a **playerctl/AppleScript fallback** so basic control works even without Premium on Linux/macOS.\n- 🔒 **Private by design** — tokens in your OS keychain, preferences in a local file, nothing phoned home.\n\n## How it works\n\n```\n Claude Code session\n        │\n   hooks (UserPromptSubmit / SessionStart)   ← ~5ms, non-blocking\n        │  one-line event over a Unix socket\n        ▼\n   Cadence MCP server  ── the single \"brain\" ──────────────┐\n        │                                                   │\n   ┌────┴─────┬───────────────┬──────────────┬─────────────┤\n detect     curation       learning        Spotify       local\n work mode  9-vibe map   (local, no-ML)    Web API     playerctl\n                                                        / AppleScript\n        ▲\n   slash commands (/cadence:play, /cadence:vibe, …) → mcp__cadence__* tools\n```\n\nOne MCP server owns everything (OAuth, state, curation, learning, playback).\nHooks are deliberately dumb — they fire a tiny event at the brain and exit\nimmediately, so they never stall your turn. Discovery is built entirely on\nSpotify's **surviving** API surface (search + your own library) and a local,\nfully-deterministic preference model — no ML training on Spotify content.\n\n## Install\n\n\u003e **Requires:** Node.js ≥ 18, a free Spotify account (Premium for Web API playback\n\u003e control — see [limitations](#spotify-2026-limitations-read-this)), and your own\n\u003e Spotify app Client ID (one-time, 2 minutes — below).\n\n### 1. Create your Spotify app (one time)\n\n1. Go to the [Spotify Developer Dashboard](https://developer.spotify.com/dashboard) → **Create app**.\n2. Add this exact **Redirect URI**: `http://127.0.0.1:8888/callback`\n   - use the `127.0.0.1` loopback IPv4 literal — **`localhost` is rejected by Spotify**\n   - `http` (not `https`) is allowed because it's loopback\n   - if port `8888` is taken on your machine, set a different `auth_port` in the\n     plugin config and register the matching `http://127.0.0.1:\u003cport\u003e/callback`\n3. Copy the **Client ID**.\n\n### 2. Add the plugin\n\n```\n/plugin marketplace add lomartins/cadence\n/plugin install cadence@cadence-marketplace\n```\n\nWhen prompted, paste your **Client ID** and pick your **market** (e.g. `US`, `GB`, `BR`).\n\n### 3. Connect \u0026 play\n\n```\n/cadence:connect      # opens your browser, waits for the callback, shows status\n/cadence:play         # start focus music for what you're doing\n```\n\n`connect` blocks until you click **Agree** in the browser, then reports the live\nconnection status.\n\n**Auto-switch** is on by default but deliberately gentle: it never cuts the\ncurrent track — it **queues the new vibe to play next**, so your song finishes\nfirst. It only acts when music is **already playing** and only in response to\n**your prompts** (never tool activity), with a 4-minute debounce, and never\nstarts music on its own. Manual `/cadence:vibe` / `/cadence:play` switch\nimmediately (that's your call). Turn auto off any time with `/cadence:auto off`.\n\n## Commands\n\nPlugin commands are namespaced under `cadence:` (type `/cadence:` to see them all):\n\n| Command | What it does |\n|---------|--------------|\n| `/cadence:connect [url]` | Authorize Spotify (waits for callback). Optional pasted URL for headless/SSH |\n| `/cadence:disconnect` | Clear stored tokens |\n| `/cadence:play [vibe] [0-4]` | Start music for the current task |\n| `/cadence:pause` · `/cadence:resume` · `/cadence:skip` | Transport controls |\n| `/cadence:vibe \u003cslug\u003e` | Switch vibe |\n| `/cadence:intensity \u003c0-4\u003e` | Energy: 0 minimal … 4 peak |\n| `/cadence:auto [on\\|off\\|toggle]` | Automatic switching |\n| `/cadence:love` · `/cadence:dislike` · `/cadence:ban` | Teach your taste |\n| `/cadence:status` | What's happening |\n| `/cadence:reset [all\\|vibe]` | Reset learned preferences |\n| `/cadence:focus [vibe] [0-4]` | Shortcut to start instantly |\n\nYou can also just *talk* to Claude: \"play something calmer\", \"I love this one\",\n\"stop changing the music\" — the bundled skill maps that to the right MCP tool.\n\n## The vibes\n\n| Vibe | For | Character |\n|------|-----|-----------|\n| `deep-focus` | implementation / deep-focus coding | lo-fi, ambient, chillhop — lyric-free, steady |\n| `steady-flow` | debugging | warm chillhop / nu-jazz — predictable, frustration-buffering |\n| `wordless-write` | writing \u0026 docs | solo piano / neoclassical — zero lyrics, protects verbal WM |\n| `open-think` | planning / architecture | ambient / generative — spacious, aids divergent thinking |\n| `calm-read` | code review / reading | quiet ambient / drone — low-arousal, preserves comprehension |\n| `alert-study` | learning / research | chillhop / baroque — alert but unobtrusive |\n| `momentum` | repetitive / mechanical | house / nu-disco / funk — upbeat, lyrics OK |\n| `decompress` | breaks | indie folk / bossa nova — high-valence, restorative |\n| `drive` | crunch / shipping | DnB / techno / epic score — high-energy, propulsive |\n\nEach vibe carries an intensity scale (0–4) that widens/narrows the BPM and energy\nband of the search. Rationale for every choice lives in\n[`src/data/presets.json`](src/data/presets.json).\n\n## How learning works\n\nEvery signal — explicit (love/like/dislike/ban/more) and implicit (completed,\nskipped-early, replayed, accepted/rejected auto-switch) — is appended to a local\n`feedback.jsonl` and folded into per-vibe preference profiles: artist/genre/track\nscores (weighted updates + exponential decay), an audio-intent centroid, and a\ntime-of-day histogram. Candidate tracks are ranked with an explainable weighted\nsum, and selection is **epsilon-greedy** (explore vs exploit) with a per-artist\ndiversity cap so it never goes stale.\n\nIt is **deterministic statistics, not ML** (counts, decay, Welford mean/var) —\nboth to stay explainable and to respect Spotify's terms. `state.json` is just a\nfold over the log — it can be recomputed from scratch (the `rebuild` tool).\n\nEverything customizable lives in `config.json` (ranking weights, signal deltas,\nthresholds, decay half-life, explore epsilon, auto-switch debounce/confidence).\n\n## Privacy\n\n- **Local only.** No telemetry. The only network calls are to *your own*\n  authenticated Spotify API.\n- **Tokens** live in your OS keychain (libsecret / Keychain / Credential Manager),\n  falling back to a `0600` file. Never in `state.json`, never in the repo.\n- **Track titles are not stored** by default (`privacy.store_track_titles: false`) —\n  only opaque Spotify URIs.\n- `/cadence:reset` (plus `export` / `forget \u003curi\u003e` / `rebuild` — just ask Claude) give you full control.\n\n## Spotify 2026 limitations (read this)\n\nSpotify heavily restricted the Web API for new apps (Nov 2024 + Feb/Mar 2026).\nCadence is built around what *survives*, but you should know:\n\n- **You supply your own Client ID.** A dev-mode app is capped at **5 users**, so\n  sharing one app doesn't scale — each user registers their own (2 min, above).\n- **The app owner (you) must have an active Spotify Premium** subscription for the\n  app to function at all, and **playback control** (play/pause/skip) requires the\n  listening account to be Premium.\n- **No Premium?** On **Linux** (`playerctl`) and **macOS** (AppleScript) Cadence\n  falls back to controlling your desktop Spotify app for play/pause/next (no track\n  selection). Windows without Premium can't control playback.\n- **Recommendations / audio-features / related-artists endpoints are gone** for new\n  apps — Cadence discovers via Search + your library instead, which is why curated\n  search queries and your own taste do the heavy lifting.\n- **Refresh tokens expire after ~6 months** — you'll re-run `/cadence:connect`\n  about twice a year.\n\n## Develop\n\n```bash\nnpm install        # also builds dist/ via the prepare hook\nnpm run build      # esbuild bundle -\u003e dist/\nnpm run typecheck  # tsc --noEmit\nnpm test           # vitest\nnpm run dev        # run the MCP server directly (uses .env)\n```\n\nArchitecture details: [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md).\n\n## License\n\nMIT © Luisa Martins. See [LICENSE](LICENSE).\n\n\u003cp align=\"center\"\u003e\u003csub\u003eBuilt to keep you in flow. 🎧\u003c/sub\u003e\u003c/p\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flomartins%2Fcadence","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flomartins%2Fcadence","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flomartins%2Fcadence/lists"}