SkillAgentSearch skills...

Scribbletune

Create music with JavaScript

Install / Use

/learn @scribbletune/Scribbletune
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

<p align="center"> <img width="64" src="https://scribbletune.com/images/scribbletune-logo.png" alt="Scribbletune"> </p> <h1 align="center">Scribbletune</h1> <p align="center"> Create music with JavaScript. Use simple strings and arrays to craft rhythms, melodies, and chord progressions — then export MIDI files or play them live in the browser with <a href="https://tonejs.github.io/">Tone.js</a> or use the CLI to directly emit MIDI file from your terminal. </p> <p align="center"> <a href="https://www.npmjs.com/package/scribbletune"><img src="https://img.shields.io/npm/v/scribbletune.svg" alt="npm version"></a> <a href="https://www.npmjs.com/package/scribbletune"><img src="https://img.shields.io/npm/l/scribbletune.svg" alt="license"></a> </p>

Install

npm install scribbletune

Quick start

Option 1: CLI

If you installed Scribbletune globally via npm i -g scribbletune then you can directly use scribbletune as the command. If you installed it locally via npm i scribbletune then please use npx scribbletune as the command.

Run modes:

# Global install
npm install -g scribbletune
scribbletune --help

# Local/project install
npm install scribbletune
npx scribbletune --help

Quick command examples:

Command format

scribbletune --riff <root> <mode> <pattern> <subdiv> [options]
scribbletune --chord <root> <mode> <pattern> <subdiv> <progression|random> [options]
scribbletune --arp <root> <mode> <pattern> <subdiv> <progression|random> [options]

Progression input rules for --chord and --arp:

1645            # degree digits
"I IV vi V"     # roman numerals (space separated)
I,IV,vi,V       # roman numerals (comma separated)
random          # generated progression
CM-FM-Am-GM     # explicit chord names (`root` and `mode` are ignored)

Common options:

--outfile <file.mid>  # default: music.mid
--subdiv <4n|8n|1m...>
--sizzle [sin|cos|rampUp|rampDown] [reps]
--sizzle-reps <number>
--amp <0-127>
--accent <x--x...>
--accent-low <0-127>
--style <letters>     # riff motif/style, e.g. AABC
--fit-pattern         # explicit enable (already enabled by default)
--no-fit-pattern      # disable automatic pattern fitting
--bpm <number>        # your DAW may or may not support it

Note: if your pattern uses [ and ] (for subdivisions), quote it in shell:

scribbletune --arp C3 major 1 'x-x[xx]-x-[xx]' 16n

Pattern helpers:

x.repeat(4)       # -> xxxx
'x-x[xx]'.repeat(2)
2(x-x[xx])        # prefix repeat shorthand
(x-x[xx])2        # suffix repeat shorthand

--riff examples

# Basic riff from scale
scribbletune --riff C3 phrygian x-xRx_RR --outfile riff.mid

# With motif/style and positional subdiv
scribbletune --riff C3 phrygian x-xRx_RR 8n --style AABC --sizzle sin 2 --outfile riff-aabc.mid

# Set riff subdivision via positional arg
scribbletune --riff C3 phrygian x-xRx_RR 8n --style AABC --outfile riff-8n.mid

# Pattern with subdivisions (quote [] in shell)
scribbletune --riff C3 phrygian 'x-x[xx]-x-[xx]' 8n --style AABC --outfile riff-subdiv.mid

Riff + motif note:

  • --style creates riff sections by repeating the full pattern per letter.
  • Example: --style AABC with pattern x-x[xx] creates 4 sections: A, A, B, C.
  • Repeated letters reuse the exact same generated section (same rhythm and same notes, including random R choices).

--chord examples

# Degree digits (resolved against root/mode)
scribbletune --chord C3 major xxxx 1m 1645 --sizzle cos 1 --outfile chords-1645.mid

# Roman numerals (space/comma separated)
scribbletune --chord C3 major xxxx 1m "I IV vi V" --outfile chords-roman.mid

# Random progression
scribbletune --chord C3 major xxxx 1m random --outfile chords-random.mid

# Explicit chord names (root/mode currently ignored for this style)
scribbletune --chord C3 major xxxx 1m CM-FM-Am-GM --outfile chords-explicit.mid

# Subdivisions in pattern
scribbletune --chord C3 major 'x-x[xx]-x-[xx]' 8n I,IV,vi,V --outfile chords-subdiv.mid

--arp examples

# Arp from degree progression
scribbletune --arp C3 major xxxx 1m 1736 --sizzle cos 4 --outfile arp-1736.mid

# Single degree "1" means tonic chord in the chosen key/mode
scribbletune --arp C3 major xxxx 4n 1 --outfile arp-degree-1.mid

# Arp from explicit chords
scribbletune --arp C3 major xxxx 1m CM-FM-Am-GM --count 4 --order 1234 --outfile arp-explicit.mid

# Custom note order inside each arpeggiated chord (one-based)
scribbletune --arp C3 major xxxx 4n 1 --order 2143 --outfile arp-order-2143.mid

# Same custom order using local dist build
node dist/cli.cjs --arp C3 major xxxx 4n 1 --order 2143 --outfile arp-order-local.mid

# Auto-fit is default (single x expands to full generated arp length)
scribbletune --arp C3 major x 4n 1736 --outfile arp-fit-default.mid

# Disable auto-fit if you want a short clip
scribbletune --arp C3 major x 4n 1736 --no-fit-pattern --outfile arp-no-fit.mid

--order behavior:

  • One-based order is supported (1234, 2143) and is recommended.
  • Zero-based order is also accepted for backward compatibility (0123, 1032).

Run scribbletune --help to see the latest CLI usage text.

Option 2: Node.js

import { scale, clip, midi } from "scribbletune";

const notes = scale("C4 major");
const c = clip({ notes, pattern: "x".repeat(8) });

midi(c, "c-major.mid");

Run it with node and open the .mid file in Ableton Live, GarageBand, Logic, or any DAW.

Option 3: Browser (with Tone.js)

Scribbletune's browser entry point adds Session, Channel, and live clip() support on top of Tone.js.

import { Session } from "scribbletune/browser";

const session = new Session();
const channel = session.createChannel({
  instrument: "PolySynth",
  clips: [
    { pattern: "x-x-", notes: "C4 E4 G4" },
    { pattern: "[-xx]", notes: "C4 D#4" },
  ],
});

await Tone.start();
Tone.Transport.start();
channel.startClip(0);

Standalone sample clip (no Session/Channel needed)

import { clip } from "scribbletune/browser";

const kickClip = clip({
  sample: "https://scribbletune.com/sounds/kick.wav",
  pattern: "x-x-",
});

const btn = document.querySelector("#btn");

btn.addEventListener("click", async () => {
  await Tone.start();
  Tone.Transport.start();
  kickClip.start(0);
});

Core concepts

Pattern language

Scribbletune uses a simple string notation to describe rhythms:

| Char | Meaning | | ---- | ----------------------------------------------- | | x | Note on | | - | Note off (rest) | | _ | Sustain previous note | | R | Random note (from randomNotes pool) | | [] | Subdivide (e.g. [xx] = two notes in one beat) |

"x---x---x-x-x---"; // basic kick pattern
"[xx][xx]x-x-"; // hihat with subdivisions
"x___"; // one long sustained note

Scales and chords

Powered by harmonics:

import { scale, chord, scales, chords } from "scribbletune";

scale("C4 major"); // ['C4', 'D4', 'E4', 'F4', 'G4', 'A4', 'B4']
chord("CM"); // ['C4', 'E4', 'G4']
scales(); // list all available scale names
chords(); // list all available chord names

Arpeggios

import { arp } from "scribbletune";

arp({ chords: "CM FM", count: 4, order: "0123" });
// ['C4', 'E4', 'G4', 'C5', 'F4', 'A4', 'C5', 'F5']

Chord progressions

import { progression, getChordsByProgression } from "scribbletune";

progression("M", 4); // e.g. ['I', 'ii', 'V', 'IV']

getChordsByProgression("C4 major", "I IV V IV");
// 'CM_4 FM_4 GM_4 FM_4'

Browser API

The browser entry point (scribbletune/browser) provides everything above plus:

Session and Channel

import { Session } from "scribbletune/browser";

const session = new Session();
const drums = session.createChannel({
  sample: "https://scribbletune.com/sounds/kick.wav",
  clips: [{ pattern: "x---x---" }, { pattern: "x-x-x-x-" }],
});

const synth = session.createChannel({
  instrument: "PolySynth",
  clips: [{ pattern: "x-x-", notes: "C4 E4 G4" }],
});

await Tone.start();
Tone.Transport.start();

// Start clips independently
drums.startClip(0);
synth.startClip(0);

// Switch patterns on the fly
drums.startClip(1);

// Or start a row across all channels
session.startRow(0);

Channel options

Channels accept various sound sources:

// Built-in Tone.js synth (by name)
{ instrument: 'PolySynth' }

// Pre-built Tone.js instrument
{ instrument: new Tone.FMSynth() }

// Audio sample URL
{ sample: 'https://example.com/kick.wav' }

// Multi-sample instrument
{ samples: { C3: 'piano-c3.wav', D3: 'piano-d3.wav' } }

// With effects
{ instrument: 'PolySynth', effects: ['Chorus', 'Reverb'] }

API reference

| Export | Description | | ---------------------------------------- | --------------------------------------------------------------------------- | | clip(params) | Create a clip — returns note objects (Node.js) or a Tone.Sequence (browser) | | midi(clip, filename?) | Export a clip to a MIDI file | | scale(name) | Get notes of a scale, e.g. 'C4 minor' | | chord(name) | Get notes of a chord, e.g. 'CM' | | scales() | List all available scale names | | chords() | List all available chord names | | arp(params)

View on GitHub
GitHub Stars3.8k
CategoryDevelopment
Updated1d ago
Forks236

Languages

TypeScript

Security Score

100/100

Audited on Apr 3, 2026

No findings