suggest-sfx — the SFX pass skill
Step 4 of the AI Video Editor pipeline — the SFX pass.
by hassancs91·MIT license·★ 330 Stars on the repo·GitHub ↗
npx degit hassancs91/claude-youtube-editor/.claude/skills/suggest-sfx#main ~/.claude/skills/suggest-sfxChecked ·commit main
Inside this skill
SKILL.md · the author's own words# suggest-sfx — the SFX pass Step 4 of the pipeline: take a video with its master cut + baked visual beats and add **tasteful sound effects**, synced to the visual beats and the narration, drawn from a **shared, growing SFX library**. Work **collaboratively and beat-by-beat**; the user audits the plan and gives notes. Same shape as the rest of the pipeline: a **declarative plan** (`sfx-plan.json`) is the source of truth → a **tool** consumes it (`tools/mix_sfx.py`) → a **library** grows (`media/library/sfx/`) → a **hard USER-AUDIT gate** before anything is mixed. Sound taste is a brand contract — read **`brand.md` §10** every time. The house style is calm/premium (Linear / Anthropic / Vercel), felt-not-heard, always under the voice. NOT MrBeast-loud. ## Inputs (read these first, every session) - **`brand.md` §10 (Sound design)** — the SFX taste contract: subtlety, density, palette, levels, sync,
Word-for-word excerpt, not a result. Read the full SKILL.md ↓
Files of suggest-sfx — the SFX pass
Show the full text155 lines
suggest-sfx — the SFX pass
Step 4 of the pipeline: take a video with its master cut + baked visual beats and add tasteful sound effects, synced to the visual beats and the narration, drawn from a shared, growing SFX library. Work collaboratively and beat-by-beat; the user audits the plan and gives notes.
Same shape as the rest of the pipeline: a declarative plan (sfx-plan.json) is the source of
truth → a tool consumes it (tools/mix_sfx.py) → a library grows (media/library/sfx/) → a hard
USER-AUDIT gate before anything is mixed.
Sound taste is a brand contract — read brand.md §10 every time. The house style is calm/premium
(Linear / Anthropic / Vercel), felt-not-heard, always under the voice. NOT MrBeast-loud.
Inputs (read these first, every session)
brand.md§10 (Sound design) — the SFX taste contract: subtlety, density, palette, levels, sync, signature motifs, source policy. Non-negotiable.videos/video-N/work/timeline.json— the shots and their master spans +type(cutaway/overlay). The cut-in/out boundaries are your transition (whoosh) candidates.videos/video-N/work/edited-transcript.json— word-level times (ms) in the MASTER timeline. Sync cues to these words (a pop on "boom", a chime on "free").- The shot sources
remotion/src/shots/video-N/*.tsx— the INTERNAL animation frames are where the real visual beats are (toggle flip, image reveal, page flip, badge pop). Read the shot, convert its local frame to master time:at_s = shot.master_in_s + local_frame / shot.fps. Do not guess — the cue must land on the exact frame the thing happens. media/library/sfx/catalog.json+palette.json— the library you draw from and grow.
The library (media/library/sfx/) — the durable asset
media/library/sfx/palette.json— generation recipes: generic, reusable sound ids + prompts + duration + tags. The source of truth for what the library SHOULD contain.media/library/sfx/catalog.json— the manifest of what EXISTS:{id, file, category, tags, duration_s, peak_dbfs, loudness_lufs, source, model, license, prompt, used_in}per clip. Written bygen_sfx.py.media/library/sfx/clips/*.mp3— loudness-normalized clips (~−20 LUFS, −1.5 dBFS ceiling) so a plan's per-cuegain_dbis perceptually meaningful.- Library-first, always. Reuse an existing clip before generating. Name/tag clips GENERICALLY
(
ui-toggle-on,whoosh-soft,pop-reveal) so future videos reuse them — the library is the durable asset, each video is one draw from it. Only genuinely-missing sounds get added topalette.jsonand generated. (SFX that must live INSIDE a Remotion shot instead go inmedia/library/sfx/viastaticFile().)
Workflow
- Read brand §10 + timeline + transcript + the shot sources + catalog. Pull exact cue times: for each candidate beat, find the visual moment's local frame in the shot and/or the narration word in the transcript, and convert to master seconds.
- Decide taste with the user up front if unsettled (present-ness, density, which kinds, source) — then apply brand §10. Don't re-ask settled decisions.
- Propose the cue list — function-first. For each beat ask what it needs (brand §10): motion
(whoosh) · tension (riser) · emphasis (impact/pop) · snap (click). Score key transitions,
reveals, and tasteful click-sequences; a 3–4-shot click-sequence counts as ONE gesture. Mark genuinely
deniable texture as
"optional": true. Layer the 2–3 biggest moments (build-and-drop): riser→impact on a scripted reveal, whoosh→pop so a cut stands out — in the plan a layer is two events at the same/ adjacentat_sthat sum. Sync each cue to the VISUAL beat and often the exact word. - Library-first sourcing. For each distinct sound the plan needs, reuse a catalog clip if one fits.
For misses, add a generic recipe to
palette.jsonand generate:python tools/gen_sfx.py(ElevenLabs Sound Effects API → normalized clip → catalog). Fall back to curated royalty-free only where generation is weak; recordsource+licenseeither way. - Author
videos/video-N/work/sfx-plan.json— one event per cue,at_son the MASTER timeline. (Schema below.) - USER-AUDIT GATE (hard). Present the resolved cue sheet (
python tools/mix_sfx.py <plan> --print) and get the user's approval/notes BEFORE mixing. This is the same gate as cuts.json / the edit plan. - Mix the audition preview once approved:
python tools/mix_sfx.py videos/video-N/work/sfx-plan.json→videos/video-N/output/video-N-first60-sfx.mp4(or the plan'srender.out). Mix over any composited version with--preview <file>. Light sidechain duck under the voice + a safety limiter. Iterate on the user's notes (gains, timing, add/cut cues) — re-print, re-mix.- Verify audibility with numbers, not hope. After mixing, RMS-diff the mixed audio vs the voice-only preview at each cue window: a story-critical cue should add ≥ +4 dB, texture +1–3 dB. Inaudible knocks hide in the cue sheet alone — don't ship a cue you haven't confirmed lands.
- Transient-clip gain gotcha. Short percussive clips (knock/stamp/keys/snap) hit the −1.5 dBFS peak
ceiling BEFORE reaching the −20 LUFS loudness target, so they catalog ~3–5 dB quieter than sustained
clips. Their plan
gain_dbmust be ~3–5 dB higher than the brand §10 table implies (percussive knocks/ stamps landed at 0..+1). The audibility check above is what surfaces this. - Short-form calibration. Under a short's near-continuous narration (~2.7 w/s, few gaps) the brand §10 gain table is 4–8 dB too quiet across the board — the duck + voice masking eat everything. Short-form landed at: transitions/whooshes −3, story pops/impacts 0..+3, stamps/snaps 0..+7, layered-hero risers 0..+2. Start a short's plan there, not at the long-form table.
- Cues that sit fully UNDER continuous speech never measure — accept felt-not-heard or cut them. Short-form click-sequences measured +0 dB at ANY gain (pushed to +9 experimentally: identical) — the sidechain duck suppresses quiet clips the whole time the voice is active. Set such cues at a sane +6-ish and let them live in the word gaps, or delete them; do NOT chase them with gain (a pause would make them spike).
- Measure transients with tight windows. RMS over 0.6s dilutes a 50 ms click to nothing and an adjacent loud cue can leak in and fake a pass (a click "measured" +9.8 because a chime 0.17s later shared its window). Use ~0.3s windows for snap/pop/zap/stamp, and measure a riser at its final third (its energy is at the END).
- Character beats level — a noisy TEXTURE cannot be fixed by gain (rejected twice in testing). Static/glitchy/hummy clips read as NOISE over speech even at −4 dB; lowering them just makes quiet noise. If the user says "noisy", swap the sound's CHARACTER (clean mechanical snap) or use silence — see brand §10 "no static/glitch textures under narration".
- Save back. New clips stay in the library + catalog (they carry to the next video). Update
used_in. A security/tech-themed set (knock-solid, glitch-zap, scan-hum, trap-snap, stamp-hit, keys-typing-soft) is library-first reusable for future videos.
sfx-plan.json (the source of truth)
{
"master": "videos/video-1/reference/master.mp4", "master_fps": 60,
"catalog": "media/library/sfx/catalog.json",
"render": {
"preview": "videos/video-1/output/video-1-preview.mp4", // the composited preview to mix over
"out": "videos/video-1/output/video-1-first60-sfx.mp4",
"end_s": 60, "duck": true
},
"events": [
{ "at_s": 2.55, "sfx_id": "ui-toggle-on", "gain_db": -13, "shot": "IntroClaudeCode",
"cue": "Free Image Generator toggle flips ON (local f66-82)", "note": "signature click" },
{ "at_s": 13.03, "sfx_id": "ui-click-soft", "gain_db": -18, "optional": true, "cue": "card locks" }
]
}
at_s— MASTER-timeline seconds (same clock as timeline.json / edited-transcript.json).gain_db— dB relative to the clip's normalized level (lower = quieter). Brand §10: −12 to −18.optional: true— deniable texture;mix_sfx.py --no-optionaldrops it. Use it liberally so the audit is about the core set.cue/note— human-readable anchor (the exact frame/word) so the audit is legible.
Tooling quick reference
- Grow the library:
python tools/gen_sfx.py [--dry-run] [--only id1,id2] [--force] [--renorm].--renormre-balances existing clips to the loudness target (no API/billing). NeedsELEVENLABS_API_KEY. - Print the cue sheet (the audit artifact):
python tools/mix_sfx.py <plan> --print [--no-optional]. - Mix:
python tools/mix_sfx.py <plan> [--no-optional] [--no-duck] [--end S] [--out path]. - Scratch renders/samples go in the scratchpad, not the project.
Principles (the house style — apply them)
- Under the voice, always. SFX are seasoning; the voice is the show. Duck them, keep them quiet, never let one peak above the narration. Silence is part of the mix.
- Key transitions & reveals only. Score the signature moment of a beat, not every sub-frame. Density
~8–12 cues/min. Everything past that is
optional. - Sync to the visual beat AND the word. A click exactly on the toggle flip; a pop exactly on the reveal; a whoosh on the cutaway. Off-by-100ms reads as sloppy — use real frame/word times.
- Reusable-first. Generic names + tags so the library compounds across videos. Reuse before you generate. The library is the deliverable that outlives this video.
- Function over vibe. Pick the sound by its job — motion/tension/emphasis/snap (brand §10) — not by browsing the catalog for something that "feels right." The same few foundational sounds do the heavy lifting; more is not better. Keep signature motifs consistent (the toggle click recurs).
- Layer the big moments, keep the rest single. Build-and-drop (riser→impact, whoosh→pop) is where SFX earn their keep — but only on the 2–3 hero beats. Everywhere else, one sound, and silence between.
- Take structure, not drama. We use the pro-editor model but stay calm/premium: no cymbal-urgency risers, no trailer slams, no whoosh on every move.
- Audit before mixing. The user reads and approves
sfx-plan.jsonfirst. Non-negotiable. - Not music. No music bed here — that is the final-mix step (track + auto-ducking + final loudness).
Done = the library has the needed clips (catalogued with source+license), sfx-plan.json is authored and
audited by the user, the SFX-mixed preview is rendered and spot-checked by ear, and any new clips +
used_in are saved back to the library. Update brand.md §10 / memory if a taste decision changed.
| 1 | |
| 2 | name suggest-sfx |
| 3 | description Step 4 of the AI Video Editor pipeline — the SFX pass. Analyze a video's beats + narration and propose tasteful sound effects synced to them, drawing from (and growing) a shared, reusable SFX library, then render an SFX-mixed audition preview. Use when the user wants to "add SFX / sound effects", "suggest sfx", "score the transitions", "sound-design this beat", generate/source sound effects, build or extend the sfx library/catalog, author or audit a sfx-plan, or mix SFX over a video-N preview in this repo. Covers reading timeline + edited-transcript + brand §10, the library-first flow, generating misses with the ElevenLabs Sound Effects API, the per-video sfx-plan.json, the hard user-audit gate, and mixing with tools/mix_sfx.py (light voice ducking). Not the music bed (that is the final-mix step) and not the visual beats (that is /make-tsx). |
| 4 | |
| 5 | |
| 6 | # suggest-sfx — the SFX pass |
| 7 | |
| 8 | Step 4 of the pipeline: take a video with its master cut + baked visual beats and add **tasteful |
| 9 | sound effects**, synced to the visual beats and the narration, drawn from a **shared, growing SFX |
| 10 | library**. Work **collaboratively and beat-by-beat**; the user audits the plan and gives notes. |
| 11 | |
| 12 | Same shape as the rest of the pipeline: a **declarative plan** (`sfx-plan.json`) is the source of |
| 13 | truth → a **tool** consumes it (`tools/mix_sfx.py`) → a **library** grows (`media/library/sfx/`) → a **hard |
| 14 | USER-AUDIT gate** before anything is mixed. |
| 15 | |
| 16 | Sound taste is a brand contract — read **`brand.md` §10** every time. The house style is calm/premium |
| 17 | (Linear / Anthropic / Vercel), felt-not-heard, always under the voice. NOT MrBeast-loud. |
| 18 | |
| 19 | ## Inputs (read these first, every session) |
| 20 | |
| 21 | **`brand.md` §10 (Sound design)** — the SFX taste contract: subtlety, density, palette, levels, sync, |
| 22 | signature motifs, source policy. Non-negotiable. |
| 23 | **`videos/video-N/work/timeline.json`** — the shots and their master spans + `type` (cutaway/overlay). The |
| 24 | cut-in/out boundaries are your transition (whoosh) candidates. |
| 25 | **`videos/video-N/work/edited-transcript.json`** — word-level times (ms) in the MASTER timeline. Sync cues to |
| 26 | these words (a pop on "boom", a chime on "free"). |
| 27 | **The shot sources** `remotion/src/shots/video-N/*.tsx` — the INTERNAL animation frames are where the |
| 28 | real visual beats are (toggle flip, image reveal, page flip, badge pop). Read the shot, convert its |
| 29 | local frame to master time: `at_s = shot.master_in_s + local_frame / shot.fps`. Do not guess — the |
| 30 | cue must land on the exact frame the thing happens. |
| 31 | **`media/library/sfx/catalog.json`** + **`palette.json`** — the library you draw from and grow. |
| 32 | |
| 33 | ## The library (`media/library/sfx/`) — the durable asset |
| 34 | |
| 35 | `media/library/sfx/palette.json` — generation recipes: generic, reusable sound ids + prompts + duration + tags. |
| 36 | The source of truth for what the library SHOULD contain. |
| 37 | `media/library/sfx/catalog.json` — the manifest of what EXISTS: `{id, file, category, tags, duration_s, |
| 38 | peak_dbfs, loudness_lufs, source, model, license, prompt, used_in}` per clip. Written by `gen_sfx.py`. |
| 39 | `media/library/sfx/clips/*.mp3` — loudness-normalized clips (~−20 LUFS, −1.5 dBFS ceiling) so a plan's per-cue |
| 40 | `gain_db` is perceptually meaningful. |
| 41 | **Library-first, always.** Reuse an existing clip before generating. Name/tag clips GENERICALLY |
| 42 | (`ui-toggle-on`, `whoosh-soft`, `pop-reveal`) so future videos reuse them — the library is the durable |
| 43 | asset, each video is one draw from it. Only genuinely-missing sounds get added to `palette.json` and |
| 44 | generated. (SFX that must live INSIDE a Remotion shot instead go in `media/library/sfx/` via |
| 45 | `staticFile()`.) |
| 46 | |
| 47 | ## Workflow |
| 48 | |
| 49 | **Read** brand §10 + timeline + transcript + the shot sources + catalog. Pull exact cue times: for each |
| 50 | candidate beat, find the visual moment's local frame in the shot and/or the narration word in the |
| 51 | transcript, and convert to master seconds. |
| 52 | **Decide taste with the user up front** if unsettled (present-ness, density, which kinds, source) — then |
| 53 | apply brand §10. Don't re-ask settled decisions. |
| 54 | **Propose the cue list — function-first.** For each beat ask what it needs (brand §10): **motion** |
| 55 | (whoosh) · **tension** (riser) · **emphasis** (impact/pop) · **snap** (click). Score key transitions, |
| 56 | reveals, and tasteful click-sequences; a 3–4-shot click-sequence counts as ONE gesture. Mark genuinely |
| 57 | deniable texture as `"optional": true`. **Layer the 2–3 biggest moments** (build-and-drop): riser→impact |
| 58 | on a scripted reveal, whoosh→pop so a cut stands out — in the plan a layer is two events at the same/ |
| 59 | adjacent `at_s` that sum. Sync each cue to the VISUAL beat and often the exact word. |
| 60 | **Library-first sourcing.** For each distinct sound the plan needs, reuse a catalog clip if one fits. |
| 61 | For misses, add a generic recipe to `palette.json` and generate: `python tools/gen_sfx.py` |
| 62 | (ElevenLabs Sound Effects API → normalized clip → catalog). Fall back to curated royalty-free only where |
| 63 | generation is weak; record `source` + `license` either way. |
| 64 | **Author `videos/video-N/work/sfx-plan.json`** — one event per cue, `at_s` on the MASTER timeline. (Schema below.) |
| 65 | **USER-AUDIT GATE (hard).** Present the resolved cue sheet (`python tools/mix_sfx.py <plan> --print`) and |
| 66 | get the user's approval/notes BEFORE mixing. This is the same gate as cuts.json / the edit plan. |
| 67 | **Mix the audition preview** once approved: `python tools/mix_sfx.py videos/video-N/work/sfx-plan.json` |
| 68 | → `videos/video-N/output/video-N-first60-sfx.mp4` (or the plan's `render.out`). Mix over any composited version |
| 69 | with `--preview <file>`. Light sidechain duck under the voice + a safety limiter. Iterate on the user's |
| 70 | notes (gains, timing, add/cut cues) — re-print, re-mix. |
| 71 | **Verify audibility with numbers, not hope.** After mixing, RMS-diff the mixed audio vs |
| 72 | the voice-only preview at each cue window: a story-critical cue should add **≥ +4 dB**, texture +1–3 dB. |
| 73 | Inaudible knocks hide in the cue sheet alone — don't ship a cue you haven't confirmed lands. |
| 74 | **Transient-clip gain gotcha.** Short percussive clips (knock/stamp/keys/snap) hit the −1.5 dBFS peak |
| 75 | ceiling BEFORE reaching the −20 LUFS loudness target, so they catalog ~3–5 dB quieter than sustained |
| 76 | clips. Their plan `gain_db` must be **~3–5 dB higher** than the brand §10 table implies (percussive knocks/ |
| 77 | stamps landed at 0..+1). The audibility check above is what surfaces this. |
| 78 | **Short-form calibration.** Under a short's near-continuous narration (~2.7 w/s, few |
| 79 | gaps) the brand §10 gain table is **4–8 dB too quiet across the board** — the duck + voice masking eat |
| 80 | everything. Short-form landed at: transitions/whooshes **−3**, story pops/impacts **0..+3**, stamps/snaps |
| 81 | **0..+7**, layered-hero risers **0..+2**. Start a short's plan there, not at the long-form table. |
| 82 | **Cues that sit fully UNDER continuous speech never measure — accept felt-not-heard or cut them.** |
| 83 | Short-form click-sequences measured +0 dB at ANY gain (pushed to +9 experimentally: identical) — the |
| 84 | sidechain duck suppresses quiet clips the whole time the voice is active. Set such cues at a sane |
| 85 | +6-ish and let them live in the word gaps, or delete them; do NOT chase them with gain (a pause |
| 86 | would make them spike). |
| 87 | **Measure transients with tight windows.** RMS over 0.6s dilutes a 50 ms click to nothing and an |
| 88 | adjacent loud cue can leak in and fake a pass (a click "measured" +9.8 because a chime 0.17s |
| 89 | later shared its window). Use ~0.3s windows for snap/pop/zap/stamp, and measure a riser at its |
| 90 | final third (its energy is at the END). |
| 91 | **Character beats level — a noisy TEXTURE cannot be fixed by gain (rejected twice in testing).** |
| 92 | Static/glitchy/hummy clips read as NOISE over speech even at −4 dB; lowering them just makes quiet |
| 93 | noise. If the user says "noisy", swap the sound's CHARACTER (clean mechanical snap) or use silence — |
| 94 | see brand §10 "no static/glitch textures under narration". |
| 95 | **Save back.** New clips stay in the library + catalog (they carry to the next video). Update `used_in`. |
| 96 | A security/tech-themed set (knock-solid, glitch-zap, scan-hum, trap-snap, stamp-hit, keys-typing-soft) is |
| 97 | library-first reusable for future videos. |
| 98 | |
| 99 | ## sfx-plan.json (the source of truth) |
| 100 | |
| 101 | |
| 102 | { |
| 103 | "master": "videos/video-1/reference/master.mp4", "master_fps": 60, |
| 104 | "catalog": "media/library/sfx/catalog.json", |
| 105 | "render": { |
| 106 | "preview": "videos/video-1/output/video-1-preview.mp4", // the composited preview to mix over |
| 107 | "out": "videos/video-1/output/video-1-first60-sfx.mp4", |
| 108 | "end_s": 60, "duck": true |
| 109 | }, |
| 110 | "events": [ |
| 111 | { "at_s": 2.55, "sfx_id": "ui-toggle-on", "gain_db": -13, "shot": "IntroClaudeCode", |
| 112 | "cue": "Free Image Generator toggle flips ON (local f66-82)", "note": "signature click" }, |
| 113 | { "at_s": 13.03, "sfx_id": "ui-click-soft", "gain_db": -18, "optional": true, "cue": "card locks" } |
| 114 | ] |
| 115 | } |
| 116 | |
| 117 | |
| 118 | `at_s` — MASTER-timeline seconds (same clock as timeline.json / edited-transcript.json). |
| 119 | `gain_db` — dB relative to the clip's normalized level (lower = quieter). Brand §10: −12 to −18. |
| 120 | `optional: true` — deniable texture; `mix_sfx.py --no-optional` drops it. Use it liberally so the audit |
| 121 | is about the core set. |
| 122 | `cue` / `note` — human-readable anchor (the exact frame/word) so the audit is legible. |
| 123 | |
| 124 | ## Tooling quick reference |
| 125 | |
| 126 | Grow the library: `python tools/gen_sfx.py [--dry-run] [--only id1,id2] [--force] [--renorm]`. |
| 127 | `--renorm` re-balances existing clips to the loudness target (no API/billing). Needs `ELEVENLABS_API_KEY`. |
| 128 | Print the cue sheet (the audit artifact): `python tools/mix_sfx.py <plan> --print [--no-optional]`. |
| 129 | Mix: `python tools/mix_sfx.py <plan> [--no-optional] [--no-duck] [--end S] [--out path]`. |
| 130 | Scratch renders/samples go in the scratchpad, not the project. |
| 131 | |
| 132 | ## Principles (the house style — apply them) |
| 133 | |
| 134 | **Under the voice, always.** SFX are seasoning; the voice is the show. Duck them, keep them quiet, |
| 135 | never let one peak above the narration. Silence is part of the mix. |
| 136 | **Key transitions & reveals only.** Score the signature moment of a beat, not every sub-frame. Density |
| 137 | ~8–12 cues/min. Everything past that is `optional`. |
| 138 | **Sync to the visual beat AND the word.** A click exactly on the toggle flip; a pop exactly on the |
| 139 | reveal; a whoosh on the cutaway. Off-by-100ms reads as sloppy — use real frame/word times. |
| 140 | **Reusable-first.** Generic names + tags so the library compounds across videos. Reuse before you |
| 141 | generate. The library is the deliverable that outlives this video. |
| 142 | **Function over vibe.** Pick the sound by its job — motion/tension/emphasis/snap (brand §10) — not by |
| 143 | browsing the catalog for something that "feels right." The same few foundational sounds do the heavy |
| 144 | lifting; more is not better. Keep signature motifs consistent (the toggle click recurs). |
| 145 | **Layer the big moments, keep the rest single.** Build-and-drop (riser→impact, whoosh→pop) is where SFX |
| 146 | earn their keep — but only on the 2–3 hero beats. Everywhere else, one sound, and silence between. |
| 147 | **Take structure, not drama.** We use the pro-editor model but stay calm/premium: no cymbal-urgency |
| 148 | risers, no trailer slams, no whoosh on every move. |
| 149 | **Audit before mixing.** The user reads and approves `sfx-plan.json` first. Non-negotiable. |
| 150 | **Not music.** No music bed here — that is the final-mix step (track + auto-ducking + final loudness). |
| 151 | |
| 152 | Done = the library has the needed clips (catalogued with source+license), `sfx-plan.json` is authored and |
| 153 | **audited by the user**, the SFX-mixed preview is rendered and spot-checked by ear, and any new clips + |
| 154 | `used_in` are saved back to the library. Update brand.md §10 / memory if a taste decision changed. |
| 155 |
Discussion
Browse more free Claude skills.