lineupify
CLAUDE.md1 starsChanged 2 months agoMITView on GitHub
MCP server (TypeScript, Node 20+, stdio) that builds Spotify or Deezer playlists from festival lineups, genres/moods, similar artists, other playlists, or a blend of several people's taste. Bring-your-own Spotify client ID; Deezer mode needs no account. Read the README for features; this file is for working on the code. Skills in .claude/skills/ cover the recurring jobs: release, verify-live, add-feature, dependabot-triage, api-check.
In this repository5 other files it gives its agents.
- add-featureSkill
- api-checkSkill
- dependabot-triageSkill
- releaseSkill
- verify-liveSkill
The file
We split this CLAUDE.md into the rules it gives an agent
2 rules. About 0 are common, 0 are distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈0
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 40
Every string from a poster, an API or a playlist is untrusted: pass it through clean() (src/infra/text.ts) and keep it inside fixed table …
- Very specific: line 45
Commit messages: subject plus a short body, no trailers of any kind (no Co-Authored-By).
≈ “Common” is an estimate: at least 1 in 5 of the 26,980 CLAUDE.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Lineupify (package lineupify-mcp)
MCP server (TypeScript, Node 20+, stdio) that builds Spotify or Deezer playlists from festival lineups, genres/moods, similar artists, other playlists, or a blend of several people's taste. Bring-your-own Spotify client ID; Deezer mode needs no account. Read the README for features; this file is for working on the code.
Commands
npm ci
npm run typecheck && npm run lint && npm test # offline; must be green before any commit
npm run coverage # same suite with a report
npm run build # dist/ (the registered MCP server runs dist/index.js)
npm run bundle:mcpb # build/lineupify-<version>.mcpb for Claude Desktop
npm run test:live # live Deezer (no key)
npm run smoke:spotify # every Spotify endpoint; needs a connected account
npx tsx test/smoke/playlists.ts <public playlist link> # reads, analysis, seeds, liveSkills in .claude/skills/ cover the recurring jobs: release, verify-live, add-feature, dependabot-triage, api-check.
Layout
src/types.tsshared types, no runtime imports.src/sources/I/O clients:spotify.ts(PKCE auth, the few Web API calls Development Mode apps still have, header lists what was verified),deezer.ts(keyless),lastfm.ts(optional key).src/engine/logic, mostly pure and unit-tested:jobs.tsbackground build (seeds → resolve → rank → match → filters → dedupe → order),resolve.ts,match.ts,seeds.ts,playlists.ts(read playlists, taste profile),filters.ts,covers.ts,analyze.ts,compare.ts,draft.ts(persistence, edits, undo),render.ts(all tool text output),select.ts,normalize.ts,lineup.ts.src/tools/MCP tool handlers;src/server.tsregisters them with zod schemas and descriptions the model acts on;src/cli.tsterminal commands.src/infra/config (~/.lineupify, env vars), JSON caches, HTTP with per-host rate limits, logging (stderr only), text cleaning.test/unitoffline suite (Spotify/Deezer mocked at the module boundary, seejobs-flow.test.ts);test/unit/server.test.tsboots the real server over stdio and snapshots the tool surface;test/live,test/smokehit real APIs.notes/is gitignored local planning (roadmap, original plan). Do not reference it from tracked files.
Hard constraints (verified against the live APIs, Sept 2026)
- Spotify Development Mode apps: 5 users, owner needs Premium, no recommendations / related artists / top tracks / audio features / genres on artist objects / batch GETs, search limit 10, Spotify-made playlists 404, playlist items come back under
item. Never add a call to a removed endpoint.SPOTIFY_API_SNAPSHOTinspotify.tsrecords the verified month. - Deezer: keyless reads only; app registration closed since 2025, so no Deezer writes.
/genre/{id}/artistsand/chart/{genre}return the global chart (use playlist search instead). Errors arrive as HTTP 200 bodies (get()indeezer.tshandles codes 4 and 800). - Claude Desktop and Cursor kill tool calls at 60 s: every tool returns within ~25 s; long work goes through
startJobinjobs.tsand is polled withget_draft. - Nothing is written to Spotify before
create_playlist.LINEUPIFY_READ_ONLY=1must keep disabling writes. - Redirect URI is
http://127.0.0.1:8765/callbackexactly (http is correct for loopback; the dashboard rejects the port-less form).
Conventions
- Every string from a poster, an API or a playlist is untrusted: pass it through
clean()(src/infra/text.ts) and keep it inside fixed table layouts inrender.ts. - stdout is the MCP channel. Log only through
src/infra/log.ts; ESLint enforcesno-consoleinsrc/. - Errors are
LineupifyError(code, message, hint). Every new code goes intodocs/troubleshooting.md. - A tool or option change touches, in order:
src/types.ts, engine,src/tools/,src/server.ts, tests (runnpx vitest run test/unit/server.test.ts -uto refresh the tool-surface snapshot and review the diff),docs/reference.mdtables (tools, seeds, options, CLI, config — the exhaustive reference lives there, not in the README),docs/troubleshooting.md,CHANGELOG.mdunder the next version. - Tests are offline by default. Mock
../../src/sources/spotify.js/deezer.jswithvi.mockandimportOriginal; use a freshLINEUPIFY_HOMEtemp dir per test file. - Commit messages: subject plus a short body, no trailers of any kind (no
Co-Authored-By). - Version lives in
package.json;npm versioncopies it intomanifest.jsonandserver.jsonviascripts/sync-version.mjs. Never edit those two by hand. - Provider-aware code: a draft has
provider: 'spotify' | 'deezer'. Deezer drafts usedeezer:track:<id>URIs, emptyspotifyId, and must never reach a Spotify call; refusals usePROVIDER_NO_PUBLISH/PROVIDER_NEEDS_SPOTIFY.
Release and repo automation
- CI (
.github/workflows/ci.yml): typecheck, lint, tests, build on Node 20/22 × Linux/Windows, on push and PR. - Release (
.github/workflows/release.yml): on av*tag or manual dispatch. Publishes to npm through npm Trusted Publishing (OIDC), no token; provenance only when the repo is public; skips npm if the version exists; builds the.mcpband creates/updates the GitHub release. See thereleaseskill. - Dependabot: eslint + @eslint/js grouped, dev minors/patches grouped, TypeScript and @types/node majors ignored (typescript-eslint lags TypeScript majors; Node types track the Node 20 floor). See the
dependabot-triageskill. - npm package settings: 2FA required, bypass tokens disallowed; the trusted publisher is
SHREESHMAN/lineupify+release.yml.
Data on the user's machine
~/.lineupify/ (LINEUPIFY_HOME): config.json, tokens.json, cache/*.json, drafts/, exports/. disconnect / lineupify-mcp logout --purge removes it. Tests must never touch the real folder.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

