---
name: samplette-app
description: Installs the SAMPLETTE. desktop app — a macOS Electron GUI for the samplette skill. Sister app to COOK. and ENDGAME. The workflow is pick → GEN → drag. Pick a YouTube channel (@Musicforemptyrooms, @BigPeter1086RealMusicChannel, @freal, or any handle) or an artist/vibe from the dropdowns, hit GEN ONE / +5 / +10, and the app auto-scrapes up to 200 videos, dedups against ones it already pulled (tracked in ~/.samplock/samplette-seen.json so the same song never gets sampled twice), picks a random unseen one, downloads the audio via yt-dlp + ffmpeg, detects its key/BPM/tuning via librosa, and cooks a MIDI pack matching the sample — all streamed live via a per-step progress card with scrape → pick → download → detect → cook animations. Each GEN produces one pack folder on Desktop containing the original MP3 + a take of chords · lead · counter · melody4 · 808 · snare · hats · open_hats in the sample's exact key, drag-ready via native drag pads into FL Studio. TRIGGER when the user asks to "install SAMPLETTE", "set up samplette app", "rebuild samplette", "update samplette", "get the new samplette GUI", "make samplette.app", "install the samplette electron app", or any variant. Also trigger on "I want a GUI for samplette" or "give me the samplette desktop app" or "push samplette to my machine".
---


# SAMPLETTE. — desktop GUI for the samplette skill

Sister app to **COOK.** and **ENDGAME.** Same SYSTEM design language, different payload. **v0.2.0** — completely rewritten flow from the original "pick sample → cook takes" UI to a YouTube-auto-scrape + per-step live progress card UI.

## Flow (the new one)

1. **Pick** a source — either a YouTube channel handle or an artist/vibe from the dropdowns (mutually exclusive: picking one clears the other).
2. **GEN** — click `GEN ONE` for a single pack, or `+5` / `+10` to stack up 5 or 10 in a row.
3. **Watch** the progress card animate through five steps, streaming real-time details from the Python CLI:
   - `SCRAPE` → yt-dlp flat-playlist pulls up to 200 video IDs
   - `PICK` → deduped against `~/.samplock/samplette-seen.json`, random choice from unseen (shows a ♻ flag when the seen list had to be recycled)
   - `DOWNLOAD` → yt-dlp streams % progress (throttled to 5% steps so the IPC doesn't flood)
   - `DETECT` → librosa Krumhansl-Schmuckler key match + beat-track BPM + A=440 tuning offset in cents
   - `COOK` → midi-cook `cook_random` driven with `force_tonic` / `force_mode` / `force_tempo_band` matched to the detected key
4. **Drag** any pad (SAMPLE / CHORDS / LEAD / COUNTER / MEL4 / 808 / SNARE / HATS / OH) from the pack card straight into FL Studio via native macOS drag-and-drop.

Each GEN produces one pack. Multiple GENs = multiple packs stacked in the right-panel recent list, sorted by mtime. No video gets sampled twice (dedup persists across sessions).

## Install

```bash
bash "${CLAUDE_SKILL_DIR:-$(dirname "$0")}/scripts/install.sh"
```

…or if `CLAUDE_SKILL_DIR` isn't set, cd into the extracted skill dir:

```bash
cd <path-to-this-skill>
bash scripts/install.sh                  # default target: ~/samplette-app
bash scripts/install.sh ~/samplette      # or a custom dir
```

The installer:
1. Verifies `node`, `npm`, `python3` are available
2. Copies `scripts/project/` into `~/samplette-app` (or the provided target), preserving `node_modules` if present for a faster rebuild
3. Runs `npm install`
4. Runs `npm run install-app` — electron-builder produces an unsigned arm64 `.app`, copies to `/Applications/SAMPLETTE..app`, strips xattrs, and launches it

After install, the app window shows:
- Stage-left: SAMPLETTE. display title, description, two-dropdown picker, `GEN ONE` / `+5` / `+10` buttons, status line, editorial footer
- Stage-right: `[ RECENT PACKS ]` header with REFRESH button, scrolling list of pack cards

## Bundled payload

`scripts/project/assets/` ships with everything the app needs:

- `samplette_cli.py` — Python CLI with subcommands: `library`, `packs`, `cook`, `scrape-channel`, `search`, `gen`. Emits newline-delimited JSON so the Electron main process can stream events to the renderer in real time.
- `samplette_core.py` — the standalone samplette skill logic (library read, key parse, tuning detect, midi-cook driver)
- `styles.py` + `midi_writer.py` — vendored from midi-cook (the cooker engine with all 18 engines and 7 voicing styles)
- `system.css` + `system.js` — SYSTEM design language (IRIS/pentboyz aesthetic)
- `icon.icns` + `icon.png` — app icon

The app is self-contained. No runtime dependency on the standalone `samplette` or `midi-cook` skills.

## IPC event stream

The renderer subscribes to `sp:line` and receives events during `gen`:

```jsonl
{"type":"step",    "step":"scrape",   "state":"active",   "detail":"searching…"}
{"type":"step",    "step":"scrape",   "state":"done",     "detail":"50 candidates"}
{"type":"step",    "step":"pick",     "state":"active",   "detail":"deduping…"}
{"type":"video",   "id":"GHy75KNqMDQ","title":"Aaliyah - 4 Page Letter (Original Video)","url":"https://..."}
{"type":"step",    "step":"pick",     "state":"done",     "detail":"Aaliyah - 4 Page Letter…","sampleTitle":"...","sampleUrl":"..."}
{"type":"step",    "step":"download", "state":"active",   "detail":"yt-dlp + ffmpeg…"}
{"type":"step",    "step":"download", "state":"active",   "detail":"50% of 4.87MiB", "progress":0.5}
{"type":"step",    "step":"download", "state":"done",     "detail":"6.7 MB"}
{"type":"step",    "step":"detect",   "state":"active",   "detail":"librosa chroma…"}
{"type":"step",    "step":"detect",   "state":"done",     "detail":"D Major · 117 BPM · -2¢","key":"D Major","bpm":117,"cents":-2.0}
{"type":"sample",  "title":"...",     "key":"D Major",    "bpm":117, "cents":-2.0,"mp3Path":"...","sourceUrl":"..."}
{"type":"step",    "step":"cook",     "state":"active",   "detail":"jrhit_melodic · close"}
{"type":"take",    "idx":1,           "engine":"jrhit_melodic","voicing":"close","tempo":129,"takePath":"..."}
{"type":"step",    "step":"cook",     "state":"done",     "detail":"jrhit_melodic · close · 129 BPM"}
{"type":"done",    "packPath":"/Users/.../Aaliyah - 4 Page Letter (Original Video) pack"}
```

## PATH handling (.app bundle quirk)

macOS launches `.app` bundles with a minimal `PATH` that doesn't include Homebrew's `/opt/homebrew/bin`. The app handles this in two places so yt-dlp and ffmpeg always resolve:

1. `main.js` — augments the env passed to the spawned Python with `/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:...`
2. `samplette_cli.py` — prepends the same dirs to `os.environ["PATH"]` as a backup, in case the Electron augmentation gets lost

## Dedup file

`~/.samplock/samplette-seen.json` is a JSON array of YouTube video IDs that have been pulled. The `gen` command filters these out of the candidate pool before picking. Delete the file to reset (e.g., if you want to re-pull something).

## Requirements

- **macOS** (arm64 or x64)
- **Node 18+** and `npm`
- **Python 3.9+** on PATH (stdlib is enough for the cook)
- **yt-dlp** and **ffmpeg** available via Homebrew at `/opt/homebrew/bin/`
- **librosa + numpy** installed in arm64 Homebrew Python at `/opt/homebrew/bin/python3` (required for key/BPM/tuning detection — without it `gen` will fail at the detect step)

```bash
brew install yt-dlp ffmpeg
/opt/homebrew/bin/python3 -m pip install librosa numpy
```

## Relation to the standalone `samplette` skill

The app covers a strict superset. The standalone `samplette` skill takes an existing MP3 from `~/.samplock/library.json` (downloaded by the Glory MP3 app) and cooks takes matching its detected key. The app does that PLUS the scrape/download/dedup pipeline, so you can generate a whole session of packs without ever leaving the window.

If you already have a sample on disk you want MIDI for, use the standalone `samplette` skill directly. If you want the app to go find one for you, use the `GEN` flow.

## Design

SYSTEM editorial-Swiss. Meta bar at top, stage split 46/54 left/right, pack cards with dotted-rule meta grid and drag pads with full hover inversion. Progress card renders with `[ GENERATING ]` + `[ SOURCE ]` bracket pair, big sample title in Inter 16/600, key·bpm·cents sub-line in JetBrains Mono, 5-row step list with pulsing dots for active and filled dots for done. All tokens pulled from the SYSTEM palette — no custom colors.

## Changelog

- **v0.2.0** (current): complete UI rewrite. Two-dropdown picker + GEN button + live progress card + YouTube auto-scrape + dedup.
- **v0.1.0**: original "pick sample from Glory MP3 library → COOK PACK" single-panel flow.
