Package Management
Resonon packages bundle reusable code and sample kits that can be installed from GitHub repositories.
Installing Packages
Section titled “Installing Packages”Install a package from GitHub using the gh:user/repo shorthand:
resonon pkg install gh:user/repoPin to a specific version tag with @:
resonon install gh:user/repo@v1.0Inside a project (where resonon.toml exists), packages install to dependencies/ relative to the project root. Outside a project, they install to ~/.config/resonon/lib/. After installation, Resonon reports what the package contains — installed kits and code exports.
Example
Section titled “Example”resonon pkg install gh:resonon/drum-kits# Installing gh:resonon/drum-kits ...# Installed 'drum-kits' [kits] to ~/.config/resonon/lib/drum-kits# Kits:# 808 — Sampler(Kit("drum-kits/808"))# vinyl — Sampler(Kit("drum-kits/vinyl"))To reinstall a package, use resonon update:
resonon update drum-kitsUpdating Packages
Section titled “Updating Packages”Update all dependencies to their latest versions:
resonon pkg update# orresonon updateUpdate a specific package:
resonon pkg update drums# orresonon update drumsUpdates re-clone each package at its pinned version tag (or latest commit if no version is set), rebuild native extensions if present, and regenerate resonon.lock.
Listing Packages
Section titled “Listing Packages”View all installed packages and their types:
resonon pkg listExample output:
Installed packages (dependencies/):
drum-kits [kits] kit: 808 — Sampler(Kit("drum-kits/808")) kit: vinyl — Sampler(Kit("drum-kits/vinyl")) my-lib [code] studio-tools [code+kits] kit: piano — Sampler(Kit("studio-tools/piano"))Each package shows its type and available kits:
| Type | Meaning |
|---|---|
[code] | Has lib.non (importable code) |
[kits] | Has kits/ directory (sampler kits) |
[code+kits] | Has both code and kits |
Kit entries also show the access path, e.g. Sampler(Kit("packagename/kitname")).
Inspecting Packages
Section titled “Inspecting Packages”Get detailed information about an installed package:
resonon pkg inspect nameThis shows:
- Package metadata and documentation (from
lib.nondoc comments) - Code exports with function signatures
- Available kits with sample counts and playback mode
Example Output
Section titled “Example Output”Package: my-lib [code+kits]
A collection of utility functions and drum kits.
Exports:
fn swing_pattern(seed, density) let default_bpm = <number>
Kits:
lo-fi — oneshot mode, 12 samples Usage: Sampler(Kit("my-lib/lo-fi"))Scaffolding Projects
Section titled “Scaffolding Projects”Create a new project with resonon init (in current directory) or resonon new (creates a new directory):
# Initialize in current directoryresonon init my-project
# Create a new directoryresonon new my-projectBoth commands accept flags to create different project types:
| Flag | Description |
|---|---|
| (none) | Plain project with main.non |
--lib | Library project with lib.non |
--kit | Kit project with kits/ directory |
--native | Native extension project with Rust crate |
Flags can be combined:
resonon new my-ext --lib --native # Library with native extensionresonon new my-pkg --lib --kit # Library with sample kitsEach project gets a resonon.toml manifest, README.md, LICENSE (MIT), .gitignore, and a git repository.
Creating Packages
Section titled “Creating Packages”A Resonon package is a directory (typically a git repo) that contains a lib.non file, a kits/ directory, or both. There’s no build step or manifest file — just write code or add samples.
Code Packages
Section titled “Code Packages”Create a code package by writing a lib.non file at the root of your project:
mkdir my-utilscd my-utilsWrite lib.non with your exported functions and values:
/// Utility functions for generative rhythms./// Provides euclidean and probabilistic pattern helpers.
/// Generate a swing pattern from a seed value./// Returns a pattern with alternating long/short durations.fn swing(seed, amount) { let base = euclid(seed, 16); base.swing(amount)}
/// Generate a fill that ramps in density.fn ramp_fill(steps, density) { let result = #[]; for i in range(steps) { if rand(i) < density * (i / steps) { result.push(bd); } else { result.push(~); } } return Pattern(result);}
/// Default BPM for live performance templates.let default_bpm = 120;
/// Internal helper — not exported.private fn quantize_to_grid(value, grid) { round(value * grid) / grid}Key points:
- All top-level
fn,let, andclassdefinitions are exported by default — consumers can access them viapackagename.name - Mark items
privateto keep them internal:private fn helper() { ... },private let internal_val = 42;, orprivate class Internal { ... } - Add
///doc comments above functions and values — they appear inresonon pkg inspectoutput - The first doc comment block (before any code) becomes the package description
Kit Packages
Section titled “Kit Packages”Create a kit package by organizing WAV files under a kits/ directory:
mkdir -p my-drums/kits/808# Copy your WAV files into the kit directorycp kick.wav snare.wav hihat.wav my-drums/kits/808/Optionally add a kit.toml for explicit configuration (see Kit Configuration Reference below):
[kit]name = "808 Classics"author = "Your Name"
[samples]bd = { files = ["kick.wav"], note = "C2" }sd = { files = ["snare.wav"], note = "D2" }hh = { files = ["hihat.wav"], note = "F#2", choke_group = 1 }Combined Packages
Section titled “Combined Packages”A package can provide both code and kits — just include both lib.non and kits/ in the same repo:
studio-tools/ lib.non # Helper functions kits/ lo-fi/ kit.toml kick_tape.wav snare_vinyl.wav piano/ kit.toml piano_c4.wavUsers can then import code and load kits from a single package:
use "std/instruments" { Sampler, Kit };use "studio-tools";
let drums = AudioTrack("drums");drums.load_instrument(Sampler(Kit("studio-tools/lo-fi")));
// Use exported helper functionslet pattern = studio-tools.swing(42, 0.6);drums << pattern;PLAY;Walkthrough: Creating a Package from Scratch
Section titled “Walkthrough: Creating a Package from Scratch”Here’s a complete example creating a drum kit package:
# 1. Create the directory structuremkdir -p beat-box/kits/vinylcd beat-box
# 2. Add your samplescp ~/samples/kick_dusty.wav kits/vinyl/cp ~/samples/snare_warm.wav kits/vinyl/cp ~/samples/hihat_crispy.wav kits/vinyl/
# 3. Write a kit.toml for explicit note mappingscat > kits/vinyl/kit.toml << 'EOF'[kit]name = "Vinyl Drums"author = "Your Name"
[samples]bd = { files = ["kick_dusty.wav"] }sd = { files = ["snare_warm.wav"] }hh = { files = ["hihat_crispy.wav"], choke_group = 1 }EOF
# 4. Test locally — Resonon searches the current directory tooresonon -e 'use "std/instruments" { Sampler, Kit }; let d = AudioTrack("d"); d.load_instrument(Sampler(Kit("beat-box/vinyl"))); d << [bd sd bd sd]; PLAY;'Kit Configuration Reference
Section titled “Kit Configuration Reference”The kit.toml file controls how samples are mapped and played. All sections are optional — Resonon auto-detects WAV files if no kit.toml is present.
Metadata ([kit])
Section titled “Metadata ([kit])”| Field | Type | Default | Description |
|---|---|---|---|
name | String | Directory name | Display name for the kit |
author | String | — | Kit author |
mode | String | "oneshot" | Playback mode: "oneshot" or "melodic" |
[kit]name = "Lo-Fi Drums"author = "Producer Name"mode = "oneshot"Oneshot mode plays each sample at a fixed pitch — standard for drum kits. Melodic mode repitches samples based on the incoming MIDI note relative to the root note — use this for tonal instruments like piano or synth samples.
Default Note Mappings ([defaults])
Section titled “Default Note Mappings ([defaults])”Map sample names to MIDI notes in bulk. Useful when you have many samples and want consistent mappings without repeating note in every [samples] entry:
[defaults]bd = "C2"sd = "D2"hh = "F#2"hh_open = "A#2"cp = "D#2"Values can be note names ("C2", "F#3") or MIDI numbers (36, 42).
Sample Configuration ([samples])
Section titled “Sample Configuration ([samples])”Each key in the [samples] table defines a sample with its settings:
| Field | Type | Default | Description |
|---|---|---|---|
files | Array of strings | — | WAV file paths (relative to kit directory). Multiple files enable round-robin playback |
note | String or number | Auto-assigned | MIDI note that triggers this sample ("C2" or 36) |
root | String or number | — | Root pitch for melodic mode ("C4" or 60) |
choke_group | Number | — | Choke group (samples in the same group cut each other off) |
velocity | Number | 1.0 | Default velocity (0.0–1.0) |
loop_start | Number | — | Loop start point (0.0–1.0, normalized position) |
loop_end | Number | — | Loop end point (0.0–1.0, normalized position) |
Basic Drum Kit
Section titled “Basic Drum Kit”[samples]bd = { files = ["kick.wav"] }sd = { files = ["snare.wav"], note = "D2" }hh = { files = ["hihat_closed.wav"], note = "F#2", choke_group = 1 }hh_open = { files = ["hihat_open.wav"], note = "A#2", choke_group = 1 }cp = { files = ["clap.wav"], note = "D#2" }Round-Robin Kit
Section titled “Round-Robin Kit”Provide multiple files per sample for automatic round-robin variation:
[samples]sd = { files = ["snare_1.wav", "snare_2.wav", "snare_3.wav"], note = "D2" }hh = { files = ["hat_soft.wav", "hat_med.wav", "hat_hard.wav"], note = "F#2" }Each trigger cycles through the files in order, adding natural variation.
Melodic Kit
Section titled “Melodic Kit”For tonal instruments, set mode = "melodic" and specify a root note for each sample:
[kit]name = "Tape Piano"mode = "melodic"
[samples]piano = { files = ["piano_c4.wav"], root = "C4" }pad = { files = ["pad_c3.wav"], root = "C3", loop_start = 0.1, loop_end = 0.95 }The root tells Resonon the original pitch of the recording. Incoming notes are repitched relative to this root — so a piano_c4.wav sample with root = "C4" plays at original pitch when triggered by C4, and shifts up/down for other notes. Use loop_start and loop_end for sustaining sounds like pads and strings.
Note Resolution
Section titled “Note Resolution”When a sample doesn’t have an explicit note, Resonon resolves it in this order:
- Explicit
notein the sample’s[samples]entry - Default mapping from the
[defaults]section - GM drum mapping based on the sample name (see table below)
- Sequential assignment starting from C2 (MIDI 36)
Common GM drum mappings recognized by name:
| Sample Name | Aliases | MIDI Note |
|---|---|---|
bd | kick, bass | C2 (36) |
sd | snare | D2 (38) |
rs | rim, rimshot | C#2 (37) |
hh | hihat, hat, ch | F#2 (42) |
hh_open | hihat_open, oh | A#2 (46) |
cp | clap | D#2 (39) |
lt | tom, tom_low | A2 (45) |
mt | tom_mid | B2 (47) |
ht | tom_high, tom_hi | D3 (50) |
crash | cy | C#3 (49) |
ride | — | D#3 (51) |
cl | clave | D#5 (75) |
cb | cowbell | G#3 (56) |
ma | maracas | A#4 (70) |
lc | conga_low | E4 (64) |
mc | conga_mid | D#4 (63) |
hc | conga_high | D4 (62) |
Auto-Detection
Section titled “Auto-Detection”If a kit directory contains WAV files but no kit.toml, Resonon auto-detects:
- Each
.wavfile becomes a sample named after the filename (without extension) - Notes are assigned via the GM drum mapping table above, or sequentially from C2 for unrecognized names
- Mode defaults to
"oneshot"
This means a minimal kit is just a folder of WAV files:
kits/ quick-kit/ bd.wav sd.wav hh.wavNo kit.toml needed — Sampler(Kit("my-package/quick-kit")) works immediately.
Publishing Packages
Section titled “Publishing Packages”Resonon packages are published by pushing to GitHub. There’s no registry or publish command — gh:user/repo maps directly to https://github.com/user/repo.git.
-
Initialize a git repo in your package directory:
Terminal window cd my-packagegit initgit add .git commit -m "Initial commit" -
Create a GitHub repository and push:
Terminal window gh repo create my-package --public --source=. --pushOr add a remote manually:
Terminal window git remote add origin git@github.com:yourname/my-package.gitgit push -u origin main -
Others install it with:
Terminal window resonon pkg install gh:yourname/my-package
Naming Conventions
Section titled “Naming Conventions”Use clear, descriptive names that indicate the package contents:
drum-kits— a collection of drum sample kitsresonon-utils— general utility functionslofi-textures— lo-fi sample kitsgenerative-tools— generative/algorithmic composition helpers
What to Include
Section titled “What to Include”A well-structured package repo typically contains:
my-package/ lib.non # Code entry point kits/ # Sample kits kit-name/ kit.toml *.wav README.md # Usage instructions LICENSE .gitignoreWhat to Exclude
Section titled “What to Exclude”Add a .gitignore to keep your repo clean:
# DAW project files*.als*.flp*.logic*.ptx
# OS files.DS_StoreThumbs.db
# Editor files*.swp*~Versioning
Section titled “Versioning”Use git tags to version your package. Consumers can pin to a specific tag in resonon.toml:
[dependencies]my-package = { source = "gh:yourname/my-package", version = "v1.0" }Or pin at install time:
resonon install gh:yourname/my-package@v1.0Without a version pin, resonon install clones the latest commit on the default branch. The resonon.lock file records the exact commit installed for each dependency. When you push updates, consumers run resonon update to get the new version.
Package Structure
Section titled “Package Structure”Packages follow a simple directory convention:
my-package/ resonon.toml # Project manifest (optional) resonon.lock # Dependency lock file (auto-generated) lib.non # Code entry point (optional) kits/ # Sample kits directory (optional) kit-name/ kit.toml # Kit configuration (optional) kick.wav snare.wav ... native/ # Rust crate for native extensions (optional) Cargo.toml src/lib.rs lib/ # Built native dylibs (optional)A package must have at least one of:
lib.nonat the package root — makes it a code package. All top-levelfn,let, andclassdefinitions are exported unless markedprivate.kits/directory with one or more subdirectories containing.wavfiles — makes it a kit package. Each subdirectory is a separate kit.
Both can coexist in a single package ([code+kits]).
Inside a project, installed packages live in dependencies/. Outside a project, they install to ~/.config/resonon/lib/. Resonon searches both locations (and the current working directory) when resolving use imports and Sampler() paths.
Project Manifest (resonon.toml)
Section titled “Project Manifest (resonon.toml)”Projects that track dependencies use a resonon.toml manifest file. It’s created automatically by resonon init or resonon new.
[package]name = "my-project"version = "0.1.0"authors = ["Your Name <email>"]resonon = "0.3.0"
[dependencies]drums = { source = "gh:resonon/drum-kits", version = "v1.0" }synths = { source = "gh:user/synths" }
[native]crate = "native"[package]
Section titled “[package]”| Field | Required | Description |
|---|---|---|
name | Yes | Package name |
version | No | Package version |
authors | No | List of authors |
resonon | No | Minimum Resonon version |
[dependencies]
Section titled “[dependencies]”Each dependency is a key-value pair where the key is the package name and the value specifies:
| Field | Required | Description |
|---|---|---|
source | Yes | Package source (gh:user/repo) |
version | No | Git tag to pin to (e.g. "v1.0") |
[native]
Section titled “[native]”Only present for packages with native Rust extensions. See Native Extensions.
| Field | Required | Description |
|---|---|---|
crate | Yes | Path to the native Rust crate (relative to project root) |
Using Installed Packages
Section titled “Using Installed Packages”Import code from a package with use:
use "packagename";
// Access exported functions and valueslet result = packagename.my_function(args);Load kits from a package with Sampler:
use "std/instruments" { Sampler, Kit };
let drums = AudioTrack("drums");drums.load_instrument(Sampler(Kit("packagename/kitname")));
drums << [bd sd bd sd];PLAY;Troubleshooting
Section titled “Troubleshooting”“Package not found” when using use — Check that the package is installed (resonon pkg list) and that you’re using the correct name. The package name is the repository name, not the [kit].name from kit.toml.
“No lib.non or kits/ found” after install — The repository exists but doesn’t follow the package structure convention. Ensure lib.non is at the repo root or kit WAV files are inside kits/{kit-name}/.
Samples not loading — Verify the kit directory contains .wav files (not .mp3, .flac, etc.). Check the path format: Sampler(Kit("package-name/kit-name")) — both parts are required.
Reinstalling a package — Use resonon update <name> to pull the latest version. If that doesn’t resolve the issue, remove and reinstall manually:
rm -rf dependencies/package-name # or ~/.config/resonon/lib/package-nameresonon install gh:user/package-nameSee Also
Section titled “See Also”- Configuration — Library and kit search paths
- Samplers — Loading and using sampler instruments
- Modules — The
useimport system - Native Extensions — Writing Rust-powered native extensions