Skip to content
Back to skills

chirp-game-audio

ASecurity

Create game sound effects and music (jumps, coins, hits, explosions, UI sounds, ambience loops, chiptune themes, jingles, audio-sprite banks) with chirp, a compact JavaScript DSL that synthesizes WAV/OGG and lets the user listen live in a browser. Use when asked to make, design or iterate on sounds or music for a game.

  • 10 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 22, 2026
ai-agentsjavascriptjavac#nodeapi

Works with

  • cli
  • api

Security analysis

A92/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro scans all 13 files and shows the line behind each finding

Scanned October 22, 2026

npx -y skills add uilianks/chirp --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of chirp-game-audio?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for chirp-game-audio
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/uilianks-chirp-game-audio/badge)](https://www.skillsdirectory.com/skills/uilianks-chirp-game-audio)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: chirp-game-audio
description: Create game sound effects and music (jumps, coins, hits, explosions, UI sounds, ambience loops, chiptune themes, jingles, audio-sprite banks) with chirp, a compact JavaScript DSL that synthesizes WAV/OGG and lets the user listen live in a browser. Use when asked to make, design or iterate on sounds or music for a game.
---

# chirp: game audio as code

You write a small `.cx.js` file; chirp synthesizes WAV (and OGG with `--ogg`) for every sound,
songs that loop seamlessly, audio-sprite banks with Howler-style JSON, and previews you can
read. Needs Node ≥ 22.18 and `npm install` once in this skill's directory.

`CHIRP` below means `node <this skill's directory>/bin/chirp.js`.

## Workflow (you can't hear: read instead)

1. Write `sounds.cx.js` (template below; more in `examples/` and `showcase/`).
2. Build: `CHIRP build sounds.cx.js --only coin,jump`. Each line prints length, peak, RMS and
   brightness. **Fix anything that says CLIPPED** (lower `vol`). Keep SFX peaks around -6 to -12 dBFS
   and similar sounds at similar levels.
3. Check it: `CHIRP info sounds.cx.js coin` prints the pitch over time (notes + Hz), so you can confirm
   slides, arpeggios and melodies. Read `out/_preview/<name>.png` (waveform + log spectrogram) for
   envelopes, filter sweeps, noise color and timing.
4. Let the user listen: start `CHIRP serve sounds.cx.js` in the background and give them the URL.
   It rebuilds on save and plays the edited sound; layers can be soloed. Ask what they hear and iterate.
   **Feedback**: the player's annotate mode (`a`) lets the user drag spans over the waveform or the
   spectrogram (a band) and pin notes to moments, then send them. When they say "check the feedback",
   read `out/_feedback/<sound>.json`: each span has `t0`/`t1` in seconds, `band` in Hz (or null),
   `color` (magenta = fix, cyan = keep, yellow = check), their `text`, the song position (`from`/`to`:
   bar, beat, step) and `loudest`: the layers playing there with their source `loc` and level. Start
   with the loudest layer's line. Comments persist between sends: check `time`.

Errors name file:line:col and suggest fixes. One broken sound doesn't stop the others.

## Template

```js
sfx("coin", { vol: 0.45 },
  tone({ wave: "square", freq: "B5", dur: 0.055, duty: 0.25, env: [0.001, 0.02, 0.6, 0.02] }),
  at(0.055, tone({ wave: "square", freq: "E6", dur: 0.18, duty: 0.25, env: [0.001, 0.05, 0.5, 0.16] })))
sfx("coin_big", { base: "coin", pitch: -5 })                              // variant: semitones

sfx("jump", { vol: 0.45 }, tone({ wave: "square", freq: 220, to: 660, slide: 0.13, dur: 0.13 }))
sfx("explosion", { vol: 0.8, fx: [crush({ bits: 8 }), drive({ amount: 1.6 })] },
  noise({ color: "brown", dur: 0.5, env: [0.002, 0.2, 0.5, 0.6], filter: { type: "lp", from: 4000, to: 150 } }),
  tone({ wave: "sine", freq: 110, to: 35, dur: 0.4 }))
sfx("rain", { dur: 8, loop: true }, noise({ color: "pink", dur: 8.5, filter: { type: "lp", cutoff: 5000 }, vol: 0.3 }))

inst("lead", { wave: "square", duty: 0.25, env: [0.004, 0.1, 0.55, 0.07], vol: 0.25 })
inst("bass", { wave: "triangle", env: [0.003, 0.06, 0.85, 0.04], vol: 0.5 })
song("theme", { bpm: 140, vol: 0.7, fx: [reverb({ mix: 0.12 })] },
  track("lead", "E5 . G5 . C6 - B5 . | A5 . G5 . E5 - - ."),
  track("bass", "C2 . C3 . C2 . C3 . | F2 . F3 . F2 . F3 ."),
  track("kick", "x . . . x . . ."), track("snare", ". . x . . . x ."), track("hat", ". x . x . x . x"))

bank("game_sfx", ["coin*", "jump", "explosion"])
```

## Essentials

- **Voices**: `tone({ wave, freq, to, slide, curve, dur, env, vol, pan, duty, arp, vibrato, tremolo, filter })`
  and `noise({ color, freq, dur, env, filter, ... })`. Pitches are Hz or notes (`"A4"`, `"C#5"`, `"Eb3"`).
  `env: [attack, decay, sustain, release]`; `dur` is the gate, the release rings after it.
- **Time**: items start together; `at(seconds, ...items)` shifts them. `play("other", { pitch, vol, pan })`
  layers another sound.
- **Effects** (sound-level `fx: [...]`): `delay reverb crush drive filter`.
- **Music**: `inst(name, voiceOpts)` or `inst(name, (freq, dur, accent) => items)`; drums built in:
  `kick snare hat openhat clap tom`. Patterns: one token per step (`steps` per beat, default 4):
  note, chord `C4+E4+G4`, `x` hit, `.` rest, `-` hold, `!` accent, `|` bar (ignored). Patterns repeat to
  the song length; build long arrangements with plain JS string joins.
- **Loops**: songs loop by default; `sfx(..., { dur, loop: true })` for ambience. Tails wrap onto
  the start, so the seam is inaudible. Non-loops trim their silent tail.
- **Game output**: `out/sfx/*.wav`, `out/music/*.wav`, `bank()` → one WAV + `{ src, sprite: { name: [ms, ms] } }`
  JSON for Howler.js / Phaser audio sprites.

Full API: [reference.md](reference.md).

## Habits that make better game audio

- Short and punchy: most SFX are 50–400 ms. Fast attacks (0.001–0.005) for hits, slower for magic.
- Pitch tells meaning: up = gain (coin, jump, power-up), down = loss (hurt, game over).
- Layer a tonal body + a noise transient for impacts (hits, landings, explosions).
- Make variants (`base` + `pitch`, different `seed`s / filters) for anything that repeats: footsteps,
  hits. Players notice identical repeats.
- Keep a family consistent: same waves and envelopes across UI sounds, same reverb across music.
- Leave headroom: music peaks ≤ -2 dBFS, SFX lower, because the game mixes them together.

Files in this skill

  • NOTICE371 B
  • SKILL.md5.3 KB
  • bin/chirp.js562 B
  • examples/basics.cx.js2.7 KB
  • package-lock.json8.6 KB
  • package.json1 KB
  • reference.md4.8 KB
  • showcase/all.cx.js93 B
  • showcase/forest_kit.cx.js7.4 KB
  • showcase/last_cup.cx.js3.8 KB
  • showcase/last_cup_iso.cx.js9 KB
  • test/chirp.test.ts7 KB
  • tsconfig.json387 B

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.