Skip to main content

aldakit

PyPI version Python 3.10+ License: MIT

A Python parser and MIDI generator for the Alda music programming language, with no install-time dependencies1.

Features

  • Alda Parser - Full parser for the Alda music language with AST generation
  • MIDI Playback - Low-latency playback via libremidi (CoreMIDI, ALSA, WinMM)
  • Audio Playback - Built-in synthesis via TinySoundFont (no external synth required)
  • MIDI Export - Save compositions as Standard MIDI Files
  • MIDI Import - Load MIDI files and convert to Alda notation
  • Alda Export - Serialize any AST back to Alda source, round-trip safe
  • Real-time Transcription - Record from MIDI keyboards and convert to Alda
  • Programmatic Composition - Build music with Python using the compose module
  • Music Theory - Scale, chord, and interval utilities
  • Transformers - Transpose, invert, augment, diminish, and more
  • Generative Music - Markov chains, L-systems, cellular automata, Euclidean rhythms
  • Interactive REPL - Syntax highlighting, auto-completion, and live playback
  • Score Checking - aldakit lint and aldakit info report what will sound wrong before you play it
  • SoundFont Management - Find, download and verify SoundFonts from the CLI
  • CLI Tools - Play, transcribe, and convert from the command line

Installation

Requires Python 3.10+

pip install aldakit

Or with uv:

uv add aldakit

Quick Start

Command Line

# Interactive REPL (default when no args)
aldakit

# Evaluate inline code
aldakit eval "piano: c d e f g"

# Play an Alda file
aldakit play examples/twinkle.alda

# Export to MIDI file
aldakit play examples/bach-prelude.alda -o bach.mid

# Use built-in audio (TinySoundFont) instead of MIDI
aldakit play -sf ~/Music/sf2/FluidR3_GM.sf2 examples/twinkle.alda
aldakit repl -sf ~/Music/sf2/FluidR3_GM.sf2

# Use audio backend with pre-configured soundfont (from config or env)
aldakit play -a examples/twinkle.alda
aldakit repl -a

# Create virtual MIDI port with custom name
aldakit repl -vp MyMIDI

# Get a SoundFont for the built-in audio backend
aldakit soundfont install

# Inspect or check a score without playing it
aldakit info examples/twinkle.alda
aldakit lint examples/twinkle.alda

Python API

import aldakit

# Play directly
aldakit.play("piano: c d e f g")

# Save to MIDI file
aldakit.save("piano: c d e f g", "output.mid")

# Play from file
aldakit.play_file("song.alda")

# List available MIDI ports
print(aldakit.list_ports())

For more control, use the Score class:

from aldakit import Score

score = Score("""
piano:
  (tempo 120)
  o4 c4 d e f | g a b > c
""")

# Play, blocking until finished
score.play(port="FluidSynth")

# Or play in the background and keep control of the playback
handle = score.play(port="FluidSynth", wait=False)
handle.is_playing()
handle.stop()

# Save to file
score.save("output.mid")

# Access internals
print(f"Duration: {score.duration}s")
print(score.ast)   # Parsed AST
print(score.midi)  # MIDI sequence

Concurrent Playback

Layer multiple sequences for polyphonic REPL-style playback:

from aldakit.midi.backends import LibremidiBackend

# Create backend with concurrent mode (default)
backend = LibremidiBackend(concurrent=True)

# Play multiple sequences - they layer on top of each other
backend.play(score1.midi)  # Starts immediately
backend.play(score2.midi)  # Layers on top of score1
backend.play(score3.midi)  # Up to 8 concurrent slots

# Check status
print(f"Active slots: {backend.active_slots}")
print(f"Playing: {backend.is_playing()}")

# Wait for all playback to complete
backend.wait()

# Or stop all playback immediately
backend.stop()

# Sequential mode - each play waits for previous to finish
backend.concurrent_mode = False
backend.play(score1.midi)  # Plays first
backend.play(score2.midi)  # Waits, then plays second

MIDI Import

Import existing MIDI files and work with them as Alda:

from aldakit import Score

# Import a MIDI file
score = Score.from_midi_file("recording.mid")

# Or use from_file (auto-detects .mid/.midi)
score = Score.from_file("song.mid")

# View as Alda source
print(score.to_alda())
# piano:
# o4 c4 d e f | g a b > c

# Play the imported MIDI
score.play()

# Export to Alda file
score.save("song.alda")

# Re-export to MIDI
score.save("output.mid")

# Import with custom quantization grid
# Default is 0.25 (16th notes), use 0.5 for 8th notes
score = Score.from_midi_file("recording.mid", quantize_grid=0.5)

Features:

  • Multi-track MIDI files (each channel becomes a separate part, and stays on its own channel when played or re-exported)
  • Channel 10 is imported as a midi-percussion part
  • Tempo detection and preservation
  • General MIDI instrument mapping across all 128 programs
  • Chord detection for simultaneous notes
  • Configurable timing quantization

Real-Time MIDI Transcription

Record MIDI input from a keyboard or controller:

import aldakit

# List available MIDI input ports
print(aldakit.list_input_ports())

# Record for 10 seconds from the first available port
score = aldakit.transcribe(duration=10)

# Play back what was recorded
score.play()

# Export to Alda source
print(score.to_alda())

# Record with options
score = aldakit.transcribe(
    duration=30,
    port_name="My MIDI Keyboard",
    instrument="piano",
    tempo=120,
    quantize_grid=0.25,  # Quantize to 16th notes
)

For more control, use TranscribeSession:

from aldakit.midi.transcriber import TranscribeSession

session = TranscribeSession(quantize_grid=0.25, default_tempo=120)

# Set a callback for note events (optional)
session.on_note(lambda pitch, vel, on: print(f"Note: {pitch}, vel={vel}, on={on}"))

# Start recording
session.start()

# Poll periodically (in a loop or timer)
import time
for _ in range(100):
    session.poll()
    time.sleep(0.1)

# Stop and get the recorded notes
seq = session.stop()
print(seq.to_alda())

Programmatic Composition

Build music programmatically using the compose module:

from aldakit import Score
from aldakit.compose import part, note, rest, chord, seq, tempo, volume

# Create a score from compose elements
score = Score.from_elements(
    part("piano"),
    tempo(120),
    note("c", duration=4),
    note("d"),
    note("e"),
    chord("c", "e", "g", duration=2),
)
score.play()

# Builder pattern with method chaining
score = (
    Score.from_elements(part("violin"))
    .with_tempo(90)
    .add(note("g", duration=8), note("a"), note("b"))
)

# Note transformations
c = note("c", duration=4)
c_sharp = c.sharpen()           # C#
c_up_octave = c.transpose(12)   # Up one octave

# Repeat syntax
pattern = seq(note("c"), note("d"), note("e"))
repeated = pattern * 4  # Repeat 4 times

# Export to Alda source
print(score.to_alda())  # "violin: (tempo 90) g8 a b"

Available compose elements:

  • Notes: note("c", duration=4, octave=5, accidental="+", dots=1)
  • Rests: rest(duration=4), rest(ms=500)
  • Chords: chord("c", "e", "g"), chord(note("c"), note("e", accidental="+"))
  • Sequences: seq(note("c"), note("d")), Seq.from_alda("c d e")
  • Parts: part("piano"), part("violin", alias="v1")
  • Attributes: tempo(120), volume(80), octave(5), panning(50)
  • Dynamics: pp(), p(), mp(), mf(), f(), ff()
  • Advanced: cram(), voice(), voice_group(), var(), var_ref(), marker(), at_marker()

Accidentals use Alda's characters: "+" (sharp), "-" (flat), "_" (natural), repeated for double accidentals. Anything else raises ValueError.

The octave a note declares is preserved through both to_alda() and MIDI generation. Octave is stateful in Alda, so a note only emits an octave change where the octave actually changes:

from aldakit import Score
from aldakit.compose import part, note

score = Score.from_elements(part("piano"), note("c", octave=5), note("d"))
print(score.to_alda())  # 'piano: o5 c d'
print([n.pitch for n in score.midi.notes])  # [72, 74]

Instrument Names

All 128 General MIDI programs are available under their Alda names. Canonical names carry the midi- prefix, and most have shorter aliases:

midi-acoustic-grand-piano:  # canonical
piano:                      # alias for the same program
midi-square-lead:           # synth lead
midi-percussion:            # drum kit on MIDI channel 10

See docs/alda-language/list-of-instruments.md for the full list. An unrecognised instrument name falls back to acoustic grand piano and reports a warning rather than failing silently:

score = Score("bogus-instrument: c d e")
print([str(d) for d in score.diagnostics])
# ["<input>:1:1: Unknown instrument 'bogus-instrument'; falling back to acoustic grand piano."]

midi-percussion (alias percussion) is placed on MIDI channel 10, where note numbers select drum sounds; key signatures and transposition do not apply to it. Melodic parts never use that channel. There are 15 melodic channels, so a score with more than 15 pitched parts reports a diagnostic that instrument assignments will collide.

Inspecting and Checking a Score

The problems the generator finds are available as values, not just as CLI output, so a build step or an editor plugin can use them:

from aldakit import inspect_score, lint_score

info = inspect_score("piano: c d e\ncello: c2")
print(info.note_count, info.duration)
for part in info.parts:
    print(part.name, part.instrument, part.channel, part.note_count)

for finding in lint_score("piano: nosuchvar"):
    print(finding.severity, finding.code, finding.message)
    # error undefined-variable Undefined variable 'nosuchvar'.

lint_score() reports unknown instruments and attributes, undefined variables and markers, notes clamped into the MIDI range, unused and redefined variables, and parts that collide on a channel. Each finding carries a code, a severity and the source position. The aldakit info and aldakit lint commands are thin wrappers over these two functions.

Scales and Chords

Build melodies and harmonies using music theory helpers:

from aldakit import Score
from aldakit.compose import part, tempo
from aldakit.compose import (
    # Scale functions
    scale, scale_notes, scale_degree, mode,
    relative_minor, relative_major,
    # Chord builders
    major, minor, dim, aug, maj7, min7, dom7,
    arpeggiate, invert_chord, voicing,
)

# Get scale pitches
c_major = scale("c", "major")       # ['c', 'd', 'e', 'f', 'g', 'a', 'b']
a_blues = scale("a", "blues")       # ['a', 'c', 'd', 'd+', 'e', 'g']

# Generate scale as playable notes
melody = scale_notes("c", "pentatonic", duration=8)

# Key relationships
rel_min = relative_minor("c")  # 'a' (C major -> A minor)
rel_maj = relative_major("a")  # 'c' (A minor -> C major)

# Build chords
c_maj = major("c")                    # C E G
a_min7 = min7("a")                    # A C E G
g_dom7 = dom7("g", inversion=1)       # B D F G (first inversion)

# Arpeggiate a chord
arp = arpeggiate(maj7("c"), pattern=[0, 1, 2, 3, 2, 1], duration=16)

# Custom voicing (spread chord across octaves)
spread = voicing(major("c"), [3, 4, 5])  # C3 E4 G5

# Create a I-IV-V-I progression
pitches = scale("c", "major")
progression = [
    major(pitches[0], duration=2),  # C major (I)
    major(pitches[3], duration=2),  # F major (IV)
    major(pitches[4], duration=2),  # G major (V)
    major(pitches[0], duration=1),  # C major (I)
]

score = Score.from_elements(
    part("piano"),
    tempo(100),
    *progression,
)
score.play()

Available scales: major, minor, harmonic-minor, melodic-minor, pentatonic, blues, chromatic, whole-tone, dorian, phrygian, lydian, mixolydian, locrian, japanese, arabic, hungarian-minor, spanish, bebop-dominant, bebop-major

Available chords: major, minor, dim, aug, sus2, sus4, maj7, min7, dom7, dim7, half_dim7, min_maj7, aug7, maj6, min6, dom9, maj9, min9, add9, power

Transformers

Transform sequences with pitch and structural operations:

from aldakit.compose import (
    note, seq,
    transpose, invert, reverse, shuffle,
    augment, diminish, fragment, loop, interleave,
    pipe,
)

# Create a motif
motif = seq(note("c", duration=8), note("d", duration=8), note("e", duration=8))

# Pitch transformers
up_fourth = transpose(motif, 5)      # Transpose up 5 semitones
inverted = invert(motif)             # Invert intervals around first note
backwards = reverse(motif)           # Retrograde

# Structural transformers
longer = augment(motif, 2)           # Double durations (8th -> quarter)
shorter = diminish(motif, 2)         # Halve durations (8th -> 16th)
first_two = fragment(motif, 2)       # Take first 2 elements
repeated = loop(motif, 4)            # Repeat 4 times (explicit)

# Chain transformations with pipe
result = pipe(
    motif,
    lambda s: transpose(s, 5),
    reverse,
    lambda s: augment(s, 2),
)

# All transforms preserve to_alda() export
print(result.to_alda())

MIDI Transformers

For post-MIDI-generation processing, use MIDI-level transformers that operate on absolute timing:

from aldakit import Score
from aldakit.midi.transform import (
    quantize, humanize, swing, stretch,
    accent, crescendo, normalize,
    filter_notes, trim, merge,
)

# Get MIDI sequence from a score
score = Score("piano: c d e f g a b > c")
midi_seq = score.midi

# Timing transformers
quantized = quantize(midi_seq, grid=0.25, strength=0.8)  # Snap to quarter-note grid
humanized = humanize(midi_seq, timing=0.02, velocity=10)  # Add subtle variations
swung = swing(midi_seq, grid=0.5, amount=0.3)            # Apply swing feel

# Velocity transformers
accented = accent(midi_seq, pattern=[1.0, 0.5, 0.5, 0.5])  # 4/4 accent pattern
crescendo_seq = crescendo(midi_seq, start_velocity=50, end_velocity=100)
normalized = normalize(midi_seq, target=100)

# Filtering and combining
filtered = filter_notes(midi_seq, lambda n: n.pitch >= 60)  # Keep notes >= middle C
trimmed = trim(midi_seq, start=0.0, end=2.0)               # First 2 seconds
merged = merge(midi_seq, another_seq)                       # Combine sequences

Note: MIDI transformers operate on absolute timing (seconds) and cannot be converted back to Alda notation.

Generative Functions

Create algorithmic compositions with generative functions:

from aldakit import Score
from aldakit.compose import part, tempo
from aldakit.compose.generate import (
    random_walk, euclidean, markov_chain, lsystem, cellular_automaton,
    shift_register, turing_machine,
)

# Random walk melody
melody = random_walk("c", steps=16, intervals=[-2, -1, 1, 2], duration=8, seed=42)

# Euclidean rhythms (e.g., Cuban tresillo: 3 hits over 8 steps)
rhythm = euclidean(hits=3, steps=8, pitch="c", duration=16)

# Markov chain
chain = markov_chain({
    "c": {"d": 0.5, "e": 0.3, "g": 0.2},
    "d": {"e": 0.6, "c": 0.4},
    "e": {"c": 0.5, "g": 0.5},
    "g": {"c": 1.0},
})
markov_melody = chain.generate(start="c", length=16, duration=8, seed=42)

# L-System (Fibonacci pattern)
from aldakit.compose import note, rest
fib = lsystem(
    axiom="A",
    rules={"A": "AB", "B": "A"},
    iterations=5,
    note_map={"A": note("c", duration=8), "B": note("e", duration=8)},
)

# Cellular automaton (Rule 110)
automaton = cellular_automaton(rule=110, width=8, steps=4, pitch_on="c", duration=16)

# Shift register (LFSR) - classic analog sequencer
lfsr = shift_register(16, bits=4, scale=["c", "e", "g", "b"], duration=16)

# Turing Machine - evolving loop (probability=0 for locked, higher for chaos)
turing = turing_machine(32, bits=8, probability=0.1, seed=42)

# Combine into a score
score = Score.from_elements(
    part("piano"),
    tempo(120),
    *melody.elements,
)
score.play()

CLI Reference

aldakit [--version] [-h] {repl,play,eval,info,lint,ports,soundfont,transcribe} ...

Subcommands

Command Description
(none) Opens the interactive REPL (default when no args)
repl Interactive REPL with syntax highlighting and auto-completion
play Play an Alda file
eval Evaluate Alda code directly
info Summarise a score: parts, instruments, channels, duration
lint Report problems in a score without playing it
ports List available MIDI ports (both input and output)
soundfont Find, download and verify SoundFonts for the audio backend
transcribe Record MIDI input and output Alda code

Global Options

Option Description
--version Show version number and exit
-h, --help Show help message

play Subcommand

aldakit play [-v] [-e CODE] [-o FILE] [--port NAME|INDEX] [-sf FILE] [-a] [-vp NAME] [--stdin] [--parse-only] [--no-wait] FILE
Option Description
FILE Alda file to play (use - for stdin)
-e, --eval CODE Play Alda code given on the command line instead of a file
-v, --verbose Verbose output
-o, --output FILE Save to MIDI file instead of playing
--port NAME|INDEX MIDI port by name or index (see aldakit ports)
-sf, --soundfont FILE Use TinySoundFont audio backend with specified SoundFont
-a, --audio Use audio backend with pre-configured soundfont
-vp, --virtual-port NAME Custom virtual MIDI port name (default: AldakitMIDI)
--stdin Read from stdin (blank line to play)
--parse-only Print AST without playing
--no-wait Return without waiting for playback to finish (playback stops when the command exits)

eval Subcommand

aldakit eval [-v] [-o FILE] [-p NAME|INDEX] [-sf FILE] [-a] [-vp NAME] [--parse-only] [--no-wait] CODE
Option Description
CODE Alda code to evaluate
-v, --verbose Verbose output
--parse-only Print AST without playing
--no-wait Return without waiting for playback to finish
-o, --output FILE Save to MIDI file instead of playing
-p, --port NAME|INDEX MIDI port by name or index
-sf, --soundfont FILE Use TinySoundFont audio backend
-a, --audio Use audio backend with pre-configured soundfont
-vp, --virtual-port NAME Custom virtual MIDI port name (default: AldakitMIDI)

repl Subcommand

aldakit repl [-v] [--port NAME|INDEX] [-sf FILE] [-a] [-vp NAME] [--sequential] [FILE]
Option Description
FILE Alda file to load on startup (use :play to hear it)
-v, --verbose Verbose output
--port NAME|INDEX MIDI port by name or index
-sf, --soundfont FILE Use TinySoundFont audio backend
-a, --audio Use audio backend with pre-configured soundfont
-vp, --virtual-port NAME Custom virtual MIDI port name (default: AldakitMIDI)
--sequential Start in sequential mode (wait for each input)

soundfont Subcommand

The audio backend needs a General MIDI SoundFont. This finds, fetches and checks them; downloads land in ~/.aldakit/soundfonts/ and are verified against a SHA256 checksum.

aldakit soundfont list              # installed files and the download catalog
aldakit soundfont install           # fetch the default (TimGM6mb, 5.8 MB)
aldakit soundfont install FluidR3_GM --force
aldakit soundfont install --all
aldakit soundfont verify            # re-check the downloaded files
aldakit soundfont path              # print the one playback would use

If you ask for audio playback and no SoundFont can be found, aldakit offers to download one, so the usual first run is a single prompt rather than an error. Non-interactive runs (scripts, CI) get the error instead of a prompt.

info Subcommand

aldakit info song.alda
aldakit info -e "piano: c d e"

Prints the parts, their instruments, MIDI programs, channels and note counts, along with the tempo, duration, variables and markers:

song.alda
  parts:    2
  notes:    5
  duration: 0:02.0 (2.00s)
  tempo:    90 bpm

  part   instrument                 prog  chan   notes
  ---------------------------------------------------
  piano  midi-acoustic-grand-piano     0     0       3
  cello  midi-cello                   42     1       2

lint Subcommand

aldakit lint song.alda
aldakit lint -e "piano: c" --strict

Reports what will make a score sound wrong without playing it: unknown instruments, undefined variables and markers, unknown attributes, notes clamped into the MIDI range, unused variables, and parts that collide on a channel.

Option Description
FILE Alda file to check (use - for stdin)
-e, --eval CODE Check Alda code given on the command line
-q, --quiet Print nothing; report through the exit status
--strict Exit non-zero on warnings as well as errors

Exit status is 0 when clean, 1 when an error was found (or any finding under --strict), and 2 when the score does not parse -- so aldakit lint --strict works as a build step.

transcribe Subcommand

aldakit transcribe [-d SEC] [-i INST] [-t BPM] [-q GRID] [-o FILE] [--port NAME] [--play] [-v] [--alda-notes] [--feel FEEL] [--swing-ratio RATIO]
Option Description
-d, --duration SEC Recording duration in seconds (default: 10)
-i, --instrument NAME Instrument name (default: piano)
-t, --tempo BPM Tempo for quantization (default: 120)
-q, --quantize GRID Quantize grid in beats (default: 0.25 = 16th notes)
-o, --output FILE Save to file (.alda or .mid)
--port NAME MIDI input port name
--play Play back the recording after transcription
-v, --verbose Show notes as they are played
--alda-notes Show notes in Alda notation (with -v)
--feel FEEL Rhythm feel: straight, swing, triplet, quintuplet
--swing-ratio RATIO Swing ratio between 0 and 1 (default: 0.67)

Examples

# Interactive REPL (default when no args)
aldakit
aldakit repl

# Evaluate inline code
aldakit eval "piano: c d e f g"

# Play a file
aldakit play examples/jazz.alda
aldakit play -v examples/jazz.alda  # verbose

# Play to a specific port (by index or name)
aldakit play --port 0 examples/twinkle.alda
aldakit play --port FluidSynth examples/twinkle.alda

# Use built-in audio (TinySoundFont) instead of MIDI
aldakit play -sf ~/Music/sf2/FluidR3_GM.sf2 examples/twinkle.alda
aldakit repl -sf ~/Music/sf2/FluidR3_GM.sf2

# Read from stdin
echo "piano: c d e f g" | aldakit play -
aldakit play --stdin

# Parse and show AST
aldakit play --parse-only examples/twinkle.alda
aldakit eval --parse-only "piano: c/e/g"

# Export to MIDI file
aldakit play examples/twinkle.alda -o twinkle.mid
aldakit eval "piano: c d e f g" -o output.mid

# List available MIDI ports
aldakit ports
aldakit ports -o  # output ports only
aldakit ports -i  # input ports only

# Record MIDI input for 10 seconds (default)
aldakit transcribe

# Record from a specific input port
aldakit transcribe --port 0
aldakit transcribe --port "My MIDI Keyboard"

# Record for 30 seconds with verbose note display
aldakit transcribe -d 30 -v

# Record with Alda-style note display
aldakit transcribe -d 10 -v --alda-notes

# Record and save to file
aldakit transcribe -o recording.alda
aldakit transcribe -o recording.mid

# Record and play back
aldakit transcribe --play

# Record with custom settings (swing feel, triplet quantization)
aldakit transcribe -d 20 -t 90 -i guitar --feel triplet --play

Configuration File

aldakit supports INI-format configuration files to set default values for common options. Configuration is loaded from these locations (in priority order):

  1. ./aldakit.ini - Project-local config (current working directory)
  2. ~/.aldakit/config.ini - User config (home directory)
  3. ALDAKIT_SOUNDFONT environment variable (for soundfont only)

CLI arguments always override config file settings.

Example Configuration

Create ~/.aldakit/config.ini:

[aldakit]
# Default SoundFont for audio backend
soundfont = ~/Music/sf2/FluidR3_GM.sf2

# Default backend: "midi" or "audio"
backend = midi

# Default MIDI output port (name or index)
port = FluidSynth

# Default tempo for REPL (BPM)
tempo = 120

# Enable verbose output by default
verbose = false

Available Options

Option Type Default Description
soundfont path none SoundFont path for audio backend
backend string midi midi = external synths/DAWs/virtual port; audio = built-in TinySoundFont
port string none Default MIDI output port name
tempo integer 120 Default tempo for REPL (BPM)
verbose boolean false Enable verbose output

Backend values:

  • midi (default): Uses libremidi for MIDI output. Sends to external synthesizers (FluidSynth, hardware), DAWs, or creates a virtual port ("AldakitMIDI") for routing.
  • audio: Uses built-in TinySoundFont for direct audio output. Requires a soundfont to be configured. No external MIDI setup needed.

Backend Selection Priority

  1. CLI -sf /path/to/soundfont.sf2 forces the audio backend with that SoundFont
  2. CLI -a / --audio forces the audio backend, using a configured or discovered SoundFont
  3. Config backend = audio uses the audio backend
  4. If MIDI output ports are available, use MIDI (default)
  5. If no MIDI ports are available and a SoundFont can be found, use audio
  6. Otherwise create a virtual MIDI port ("AldakitMIDI") and warn that nothing will be heard until a synth or DAW connects to it

A SoundFont counts as available if it is named by -sf, by soundfont in the config file, or by ALDAKIT_SOUNDFONT, or if one is discovered in a standard location such as ~/.aldakit/soundfonts/ or ~/Music/sf2/.

If aldakit play produces no sound, run aldakit ports to see whether any MIDI destination exists. With no ports and no SoundFont, MIDI is being sent to a virtual port that nothing is listening to.

Project-Local Configuration

Create aldakit.ini in your project directory to override user settings:

[aldakit]
# Use audio backend with project-specific SoundFont
backend = audio
soundfont = ./sounds/project-soundfont.sf2
tempo = 140

Interactive REPL

The REPL provides an interactive environment for composing and playing Alda code:

aldakit repl

Features:

  • Syntax highlighting
  • Auto-completion for instruments (3+ characters)
  • Command history (persistent across sessions)
  • Multi-line paste (use platform-specific paste: ctrl-v, shift-ctrl-v, cmd-v, etc.)
  • Multi-line input (Alt+Enter)
  • MIDI playback control (Ctrl+C to stop)

REPL Commands:

Command Description
:load FILE Load an Alda file (does not play)
:play [FILE] Play the loaded score, or load and play FILE
:save FILE Save the session to .alda or .mid
:ls [DIR] List Alda files and directories
:cd [DIR] Change directory
:pwd Show the current directory
:clear Forget the session so far
:ports List MIDI ports
:instruments List available instruments
:tempo [BPM] Show/set the default tempo
:stop Stop playback
:status Show playback status
:concurrent / :sequential Switch playback mode
:help Show help
:quit Exit the REPL

Open a file directly from the command line. It is loaded, not played, so the REPL is ready immediately:

$ aldakit repl examples/twinkle.alda
Loaded examples/twinkle.alda (1 part, 42 notes, 28.7s)
Type :play to hear it.

aldakit> :play
Playing examples/twinkle.alda...

Working with files inside the REPL:

aldakit> :ls
  examples/
  sketch.alda
aldakit> :load sketch.alda
Loaded sketch.alda (2 parts, 64 notes, 12.4s)
Type :play to hear it.
aldakit> :play
Playing sketch.alda...
aldakit> piano: c d e f g
aldakit> :save take-2.alda
Saved /home/you/music/take-2.alda

:load never plays: a file can be inspected, saved or edited before it is heard, and opening a long score does not tie up the prompt. :play with no argument replays whatever is loaded; :play FILE is shorthand for loading and playing in one step. Typed input still plays as soon as you press Enter.

:save writes everything accepted during the session -- typed, pasted or loaded -- as a single score. A .mid or .midi extension exports MIDI instead. Note that this is the session's source, not a recording of what you heard: in concurrent mode inputs are layered as they play, whereas the saved file is one score read top to bottom.

A file opened with :load (or given on the command line) keeps its own tempo. The REPL only prepends its default tempo to input you type that does not set one.

Alda Syntax Reference

Notes and Rests

piano:
  c d e f g a b   # Notes
  r               # Rest
  c4 d8 e16       # With duration (4=quarter, 8=eighth, etc.)
  c4. d4..        # Dotted notes
  c500ms d2s      # Milliseconds and seconds

Accidentals

c+    # Sharp
c-    # Flat
c_    # Natural
c++   # Double sharp

Octaves

o4 c    # Set octave to 4
> c     # Octave up
< c     # Octave down

Chords

c/e/g           # C major chord
c1/e/g          # Whole note chord
c/e/g/>c        # With octave change

Ties and Slurs

c1~1            # Tied notes (duration adds)
c4~d~e~f        # Slurred notes (legato)

Parts

piano: c d e

violin "v1": c d e    # With alias

violin/viola/cello "strings":   # Multi-instrument
  c d e

Attributes

(tempo 120)     # Set tempo (BPM)
(tempo! 120)    # Global tempo

(vol 80)        # Volume (0-100)
(volume 80)

(quant 90)      # Quantization/legato (0-100)

(panning 50)    # Pan (0=left, 100=right)

# Dynamic markings
(pp) (p) (mp) (mf) (f) (ff)

# Key signatures
(key-sig '(g major))     # G major (F#)
(key-sig '(d minor))     # D minor (Bb)
(key-sig "f+ c+")        # Explicit accidentals

# Transposition
(transpose 5)   # Up 5 semitones
(transpose -2)  # Down 2 semitones (Bb instrument)

Variables

riff = c8 d e f g4

piano:
  riff riff > riff

Repeats

c*4             # Repeat note 4 times
[c d e]*4       # Repeat sequence
[c d e f]*8     # 8 times

Cram (Tuplets)

{c d e}4        # Triplet in quarter note
{c d e f g}2    # Quintuplet in half note
{c {d e} f}4    # Nested cram

Voices

piano:
  V1: c4 d e f
  V2: e4 f g a
  V0:           # End voices

Markers

piano:
  c d e f
  %chorus
  g a b > c

violin:
  @chorus       # Jump to chorus marker
  e f g a

Supported Instruments

All 128 General MIDI instruments are supported. Common examples:

  • piano, acoustic-grand-piano
  • violin, viola, cello, contrabass
  • flute, oboe, clarinet, bassoon
  • trumpet, trombone, french-horn, tuba
  • acoustic-guitar, electric-guitar-clean, electric-bass
  • choir, strings, brass-section

See midi/types.py for the complete mapping.

MIDI Backend

aldakit uses libremidi via nanobind for cross-platform MIDI I/O:

  • Low-latency realtime playback
  • Virtual MIDI port support (AldakitMIDI), makes it easy to just send to your DAW.
  • Pure Python MIDI file writing (no external dependencies)
  • Cross-platform: macOS (CoreMIDI), Linux (ALSA), Windows (WinMM)
  • Supports hardware and software/virtual MIDI ports (FluidSynth, IAC Driver, etc.)
import aldakit

# List available ports
print(aldakit.list_ports())

# Play to virtual port (visible in DAWs like Ableton Live)
aldakit.play("piano: c d e f g")

# Play to a specific port
aldakit.play("piano: c d e f g", port="FluidSynth")

# Save to MIDI file
aldakit.save("piano: c d e f g", "output.mid")

Audio Backend (Built-in)

For self-contained audio playback without external synthesizers, aldakit includes a built-in audio backend powered by TinySoundFont and miniaudio:

  • Direct audio output (no FluidSynth or DAW required)
  • Cross-platform: macOS (CoreAudio), Linux (ALSA/PulseAudio), Windows (WASAPI)
  • Requires a SoundFont file (.sf2) for instrument sounds
  • Header-only libraries for minimal binary size

Basic Usage

from aldakit import Score

# Play with built-in audio (requires SoundFont)
score = Score("piano: c d e f g")
score.play(backend="audio")

# Specify SoundFont explicitly
score.play(backend="audio", soundfont="/path/to/FluidR3_GM.sf2")

SoundFont Setup

The audio backend requires a General MIDI SoundFont file. aldakit searches these locations automatically:

  • $ALDAKIT_SOUNDFONT environment variable
  • ~/Music/sf2/
  • ~/.aldakit/soundfonts/
  • /usr/share/soundfonts/ (Linux)

Option 1: Download manually

Download a SoundFont and place it in a folder such as ~/Music/sf2/:

Suggest using a sha256sum (macOs or Linux) or similar to verify file integrity after download:

% sha256sum FluidR3_GM.sf2
74594e8f4250680adf590507a306655a299935343583256f3b722c48a1bc1cb0  FluidR3_GM.sf2

% sha256sum GeneralUser-GS.sf2
c278464b823daf9c52106c0957f752817da0e52964817ff682fe3a8d2f8446ce  GeneralUser-GS.sf2

% sha256sum TimGM6mb.sf2
82475b91a76de15cb28a104707d3247ba932e228bada3f47bba63c6b31aaf7a1  TimGM6mb.sf2

On Windows (PowerShell): Get-FileHash -Algorithm SHA256

Option 2: Auto-download

from aldakit.midi.soundfont import setup_soundfont, setup_all_soundfonts

# Downloads TimGM6mb.sf2 (~6 MB) to ~/.aldakit/soundfonts/
setup_soundfont()

# Or download all available SoundFonts from the catalog
setup_all_soundfonts()

Option 3: Using SoundFontManager

For more control, use the SoundFontManager class:

from aldakit.midi.soundfont import SoundFontManager

manager = SoundFontManager()

# Find existing SoundFont
sf = manager.find()

# List all found SoundFonts
for path in manager.list():
    print(path)

# Download a specific SoundFont (with SHA256 verification)
path = manager.download("FluidR3_GM")

# Download all SoundFonts from catalog
paths = manager.setup_all()

# Verify checksums of downloaded files
results = manager.verify_checksums()
for name, valid in results.items():
    print(f"{name}: {'OK' if valid else 'FAILED'}")

# List available downloads
for name, info in manager.list_available_downloads().items():
    print(f"{name}: {info['size_mb']} MB - {info['description']}")

Option 4: Environment variable

export ALDAKIT_SOUNDFONT=/path/to/your/soundfont.sf2

Using TsfBackend Directly

from aldakit import Score
from aldakit.midi.backends import TsfBackend

# Create backend with specific SoundFont
with TsfBackend(soundfont="~/Music/sf2/FluidR3_GM.sf2") as backend:
    score = Score("piano: c/e/g")
    backend.play(score.midi)
    backend.wait()  # Block until playback completes

# Inspect SoundFont presets
backend = TsfBackend()
print(f"Presets: {backend.preset_count}")
for i in range(min(10, backend.preset_count)):
    print(f"  {i}: {backend.preset_name(i)}")

Audio vs MIDI Backend

Feature Audio (backend="audio") MIDI (backend="midi")
External synth required No Yes (FluidSynth, DAW, hardware)
Setup complexity Just needs SoundFont Requires MIDI routing
Sound quality Depends on SoundFont Depends on synth
DAW integration No Yes (virtual port)
Latency Very low Very low
Effects (reverb, etc.) No Depends on synth

Recommendation: Use backend="audio" for quick playback and standalone use. Use backend="midi" (default) for DAW integration, hardware synths, or when you need effects.

MIDI Playback Setup

Virtual Port (Recommended)

When no hardware MIDI ports are available, aldakit creates a virtual port named "AldakitMIDI". This port is visible to DAWs and other MIDI software:

  1. Start the REPL: aldakit repl
  2. In your DAW (Ableton Live, Logic Pro, etc.), look for "AldakitMIDI" in MIDI input settings
  3. Play code in the REPL - notes will be sent to your DAW

Software Synthesizer (FluidSynth)

For high-quality General MIDI playback without hardware, use FluidSynth:

# Install FluidSynth (macOS)
brew install fluidsynth

# Install FluidSynth (Debian/Ubuntu)
sudo apt install fluidsynth 

# Download a SoundFont (e.g., FluidR3_GM.sf2)
# eg. sudo apt install fluid-soundfont-gm
# Place in ~/Music/sf2/

# Start FluidSynth with CoreMIDI (macOS)
fluidsynth -a coreaudio -m coremidi ~/Music/sf2/FluidR3_GM.sf2

# In another terminal, start aldakit
aldakit repl
# aldakit> piano: c d e f g

A helper script is available in the repository:

# Set the SoundFont directory (add to your shell profile)
export ALDAPY_SF2_DIR=~/Music/sf2

# Run with default SoundFont (FluidR3_GM.sf2)
python scripts/fluidsynth-gm.py

# Or specify a SoundFont directly
python scripts/fluidsynth-gm.py /path/to/soundfont.sf2

# List available SoundFonts
python scripts/fluidsynth-gm.py --list

Hardware MIDI

Connect a USB MIDI interface or synthesizer, then:

# List available ports
aldakit ports

# Play to a specific port
aldakit play --port "My MIDI Device" examples/twinkle.alda

MIDI File Export

If you don't have MIDI playback set up, export to a file:

# Save to MIDI file
aldakit play examples/twinkle.alda -o twinkle.mid

# Open with default app
open twinkle.mid

Development

Setup

git clone https://github.com/shakfu/aldakit.git
cd aldakit
make  # Build the libremidi extension

Run Tests

make test
# or
uv run pytest tests/ -v

Architecture

aldakit architecture

License

MIT

See Also

  • Alda - The original Alda language and reference implementation
  • Alda Cheat Sheet - Syntax reference
  • Extending aldakit - Design document for programmatic API
  • libremidi - A modern C++ MIDI 1 / MIDI 2 real-time & file I/O library. Supports Windows, macOS, Linux and WebMIDI.
  • TinySoundFont - SoundFont2 synthesizer library in a single C/C++ header
  • miniaudio - Single-header audio playback and capture library
  • nanobind - a tiny and efficient C++/Python bindings
  1. Includes a rich REPL, native MIDI, and built-in audio via bundled prompt-toolkit, libremidi, and TinySoundFont respectively.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

aldakit-0.2.1.tar.gz (2.2 MB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

aldakit-0.2.1-cp314-cp314-win_amd64.whl (1.2 MB view details)

Uploaded CPython 3.14Windows x86-64

aldakit-0.2.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (877.4 kB view details)

Uploaded CPython 3.14manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

aldakit-0.2.1-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl (865.5 kB view details)

Uploaded CPython 3.14manylinux: glibc 2.27+ ARM64manylinux: glibc 2.28+ ARM64

aldakit-0.2.1-cp314-cp314-macosx_11_0_x86_64.whl (814.1 kB view details)

Uploaded CPython 3.14macOS 11.0+ x86-64

aldakit-0.2.1-cp314-cp314-macosx_11_0_arm64.whl (791.0 kB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

aldakit-0.2.1-cp313-cp313-win_amd64.whl (1.2 MB view details)

Uploaded CPython 3.13Windows x86-64

aldakit-0.2.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (877.5 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

aldakit-0.2.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl (865.2 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.27+ ARM64manylinux: glibc 2.28+ ARM64

aldakit-0.2.1-cp313-cp313-macosx_11_0_x86_64.whl (813.9 kB view details)

Uploaded CPython 3.13macOS 11.0+ x86-64

aldakit-0.2.1-cp313-cp313-macosx_11_0_arm64.whl (790.9 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

aldakit-0.2.1-cp312-cp312-win_amd64.whl (1.2 MB view details)

Uploaded CPython 3.12Windows x86-64

aldakit-0.2.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (877.6 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

aldakit-0.2.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl (865.4 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.27+ ARM64manylinux: glibc 2.28+ ARM64

aldakit-0.2.1-cp312-cp312-macosx_11_0_x86_64.whl (814.1 kB view details)

Uploaded CPython 3.12macOS 11.0+ x86-64

aldakit-0.2.1-cp312-cp312-macosx_11_0_arm64.whl (791.0 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

aldakit-0.2.1-cp311-cp311-win_amd64.whl (1.2 MB view details)

Uploaded CPython 3.11Windows x86-64

aldakit-0.2.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (879.6 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

aldakit-0.2.1-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl (867.5 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.27+ ARM64manylinux: glibc 2.28+ ARM64

aldakit-0.2.1-cp311-cp311-macosx_11_0_x86_64.whl (815.2 kB view details)

Uploaded CPython 3.11macOS 11.0+ x86-64

aldakit-0.2.1-cp311-cp311-macosx_11_0_arm64.whl (793.1 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

aldakit-0.2.1-cp310-cp310-win_amd64.whl (1.2 MB view details)

Uploaded CPython 3.10Windows x86-64

aldakit-0.2.1-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (880.1 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

aldakit-0.2.1-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl (867.8 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.27+ ARM64manylinux: glibc 2.28+ ARM64

aldakit-0.2.1-cp310-cp310-macosx_11_0_x86_64.whl (815.4 kB view details)

Uploaded CPython 3.10macOS 11.0+ x86-64

aldakit-0.2.1-cp310-cp310-macosx_11_0_arm64.whl (793.4 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

File details

Details for the file aldakit-0.2.1.tar.gz.

File metadata

  • Download URL: aldakit-0.2.1.tar.gz
  • Upload date:
  • Size: 2.2 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for aldakit-0.2.1.tar.gz
Algorithm Hash digest
SHA256 378f294921339dbe8870138d106a71fbad23f198023224b81b6608640500ac85
MD5 43090bcff96f6893bcd90a9dfe8a2204
BLAKE2b-256 c01e6c724abaf9d46d0ebb28721b41aa990f3348bd7c883641c8fc1e541b16ce

See more details on using hashes here.

File details

Details for the file aldakit-0.2.1-cp314-cp314-win_amd64.whl.

File metadata

  • Download URL: aldakit-0.2.1-cp314-cp314-win_amd64.whl
  • Upload date:
  • Size: 1.2 MB
  • Tags: CPython 3.14, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for aldakit-0.2.1-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 f5deddc1f62a44ccdf6c77baad6507bd6a20bb6408356a23e0084e6fdd579b63
MD5 0bf61a3d904fd8c4c7d7e4ac71698027
BLAKE2b-256 ce69dc4a3dc363ee82a9828568aab78b1e65337596de53f2ca5fde4af5d6d2a5

See more details on using hashes here.

File details

Details for the file aldakit-0.2.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for aldakit-0.2.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 392670fd1e7b3654465ab6d4d3f7d9f05fa44a5e57707089e5d05559f1f9e551
MD5 c6450827e4305d9ca31e2f74bf85daa9
BLAKE2b-256 2c8645aa567fc811c1865379ac738e23508670f297895c710ca92b809062d57c

See more details on using hashes here.

File details

Details for the file aldakit-0.2.1-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for aldakit-0.2.1-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 215f67851c40dd7994c8ac8a37abcb2fa69232e291eb5925ab563ff3ebab67a4
MD5 57cd29696564061efec32314cc2493cf
BLAKE2b-256 c7d6f4abcbdb0f8b9f09b485db4db0186784eaf520abe742fabe00781ca34137

See more details on using hashes here.

File details

Details for the file aldakit-0.2.1-cp314-cp314-macosx_11_0_x86_64.whl.

File metadata

File hashes

Hashes for aldakit-0.2.1-cp314-cp314-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 074b210afbeba2d587b4cdd8ab577a2b18a3dc978d43819646db3d99689050b0
MD5 577c2fa9c672121dfed6c1c95edff7b5
BLAKE2b-256 6c88c339a10e4802711887da88860a55f9e779fc04cc33c22045bfa0423d8e00

See more details on using hashes here.

File details

Details for the file aldakit-0.2.1-cp314-cp314-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for aldakit-0.2.1-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 62c009e0a84894be95564ad7a146274c4ac987348bd6365d4d1787c9a5a037a5
MD5 4ce0dbbaec847cb9763263263a689ac4
BLAKE2b-256 82cc280cd396f41536fd52c09defac63823f3186b261fad32ac8e2b23cc85cdb

See more details on using hashes here.

File details

Details for the file aldakit-0.2.1-cp313-cp313-win_amd64.whl.

File metadata

  • Download URL: aldakit-0.2.1-cp313-cp313-win_amd64.whl
  • Upload date:
  • Size: 1.2 MB
  • Tags: CPython 3.13, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for aldakit-0.2.1-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 28d2ede97152b6213fd698bd3796c9421222c0a53c654c850915c0f803541ef2
MD5 0e216ca465d58aa3a00b8b110f3dba4e
BLAKE2b-256 d344e0fa073e7cd94aa807c9050c35461d0066fe4ed2a405e2d27a1bb2f9b2c7

See more details on using hashes here.

File details

Details for the file aldakit-0.2.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for aldakit-0.2.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 5dae35225a53f7751abd67dc7e0f4ebc6887f6cd1c5900faa64cef5eec55a39c
MD5 0d17d004dad28a93844e1534ca897bce
BLAKE2b-256 507e0e035cda40d8b583f838f25664b800dddf670488c4b39aca2b0b5ac9b510

See more details on using hashes here.

File details

Details for the file aldakit-0.2.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for aldakit-0.2.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 686b214d6c77ed3ebd039bb938f07db94f132104e08ee41ac2731af78066f9ff
MD5 8eeba54e68cf3fcaae1c032c29de8fa2
BLAKE2b-256 319dc9a28b75205e5a11b04bd4fa3807b66c02ad3634495f86bc7a6c79d20822

See more details on using hashes here.

File details

Details for the file aldakit-0.2.1-cp313-cp313-macosx_11_0_x86_64.whl.

File metadata

File hashes

Hashes for aldakit-0.2.1-cp313-cp313-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 3dca1240a54390adec52484b59c1ee61999ff7e9eeee376ff404f69dbe753b3e
MD5 69fd70c98f8b4051d926d1a4578ee8ee
BLAKE2b-256 ef5faada43c7f81ade71734c3ed098153cd52f6b721e6a26e01b96a626950da8

See more details on using hashes here.

File details

Details for the file aldakit-0.2.1-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for aldakit-0.2.1-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 f36604539fc67805cb46da84f131240a6134465c56442832adaca1bb88a6615f
MD5 a750d452b88613e49ce6be378697e147
BLAKE2b-256 6eb49b2a07fc6335c0eb8baa76d59dd3f9bebe1668a842c516448c403864a86e

See more details on using hashes here.

File details

Details for the file aldakit-0.2.1-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: aldakit-0.2.1-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 1.2 MB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for aldakit-0.2.1-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 727e02a25b826b6947cd1754f193ca05b6aa068bf890191710221d36aae19487
MD5 1bb9e074d8599c06df8c20f78a6e58d2
BLAKE2b-256 7f978a2607e69b7cd653f87ce490d69941ac91b6c23c3f5e21e3f97446978a78

See more details on using hashes here.

File details

Details for the file aldakit-0.2.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for aldakit-0.2.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 35606dd1a8f0ef54ce8b9b93fa77c58631290090d0c3032b49adfe1d5dabd8b5
MD5 a1e3a3040620ade17d36843748886b40
BLAKE2b-256 2baea3a20c953b3fd77ddd6eb5bd2c5c33a77009f492aa1600afae82567aee02

See more details on using hashes here.

File details

Details for the file aldakit-0.2.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for aldakit-0.2.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 b99dc84e28fa9fafaf09b70ee81ed4169ad56dc6cb661d0e47ece6e5d4193518
MD5 cbba5e0f537056a895db8cbe4a93edf7
BLAKE2b-256 8bb6f4247fe8452d7c244df84877b92e8fa8b274aaf835d4fbbf426377082fc0

See more details on using hashes here.

File details

Details for the file aldakit-0.2.1-cp312-cp312-macosx_11_0_x86_64.whl.

File metadata

File hashes

Hashes for aldakit-0.2.1-cp312-cp312-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 f2b6cd6fc2f0dc9b8e1a10d5857771eeb08ef8416ee8c57719e115929120a8b6
MD5 4fd80e918ea67f31fab8ec51862be2bd
BLAKE2b-256 891a893b23b41071962c23e8dc7d0de30026ac47decc7d295af47131ca88d15e

See more details on using hashes here.

File details

Details for the file aldakit-0.2.1-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for aldakit-0.2.1-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 bd44e6c423bccef9a2342817f7c6806d6aa9528dc491fe046a656005afdb28bc
MD5 8b52dd162735d0108a804af88a6afe03
BLAKE2b-256 6fa582af6f1098f164e674d5092ea91158a290ee9747881b7ed39fcef5f7098c

See more details on using hashes here.

File details

Details for the file aldakit-0.2.1-cp311-cp311-win_amd64.whl.

File metadata

  • Download URL: aldakit-0.2.1-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 1.2 MB
  • Tags: CPython 3.11, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for aldakit-0.2.1-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 5fc55e4160c7907bb4c558943525d483288cbebf015ee1dbb5baad679d644a84
MD5 0c4d4763ec1432b2713bbbee34ca757f
BLAKE2b-256 2cadabdc2cd5b6d309edad589bfbadd05ea3a0707004ce077be599da6b655581

See more details on using hashes here.

File details

Details for the file aldakit-0.2.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for aldakit-0.2.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 d887616b4ec2b93dc9f773aa6b0da15064d66d7541781981781d5f027329b321
MD5 01aa87dac8322d825302bd38a1d57571
BLAKE2b-256 43ac8f7664616329f41964859277628f9354afb26063bd07138fb61b3af810b5

See more details on using hashes here.

File details

Details for the file aldakit-0.2.1-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for aldakit-0.2.1-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 6f4db8ff8c1c93b9dc35c0504cd59ac12d3fcb701cd369bc4bc20d2367e320a8
MD5 16846153d4f7d672cc33cc07e4b08a04
BLAKE2b-256 23ce4199eb8de802d110214caa3b4d6e4849a37cff4c925a50bc686017f81649

See more details on using hashes here.

File details

Details for the file aldakit-0.2.1-cp311-cp311-macosx_11_0_x86_64.whl.

File metadata

File hashes

Hashes for aldakit-0.2.1-cp311-cp311-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 19e8c8cba69ad4dc6fe0c227a7602f518bb7fa53f70d71aee03d61e12ed8e8bd
MD5 84dd3c5ce539430c7e8ae9463c18ebd7
BLAKE2b-256 c82ff498c6979f3c43f102d69de6ea943f8e760f5b3dc3ead16611df2a0b2d06

See more details on using hashes here.

File details

Details for the file aldakit-0.2.1-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for aldakit-0.2.1-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 92dc8602474cee68b03720a04eb24959eb6f5c5d7a8aa81b3f4111d78d3fdea2
MD5 261f22ae0d684b70a89e95abab46feb9
BLAKE2b-256 bb5852881b98271846a49800b36a4541a8d6e209190ab0aac4a38a879b4425dc

See more details on using hashes here.

File details

Details for the file aldakit-0.2.1-cp310-cp310-win_amd64.whl.

File metadata

  • Download URL: aldakit-0.2.1-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 1.2 MB
  • Tags: CPython 3.10, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for aldakit-0.2.1-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 1cf4cd80c5ea3e3e8264bda4e73623bf04bc0c17141157d08db5a13115d998b1
MD5 9a0fabd6667a72acde3a9de826a69df6
BLAKE2b-256 a65f96e917339168a3944bf4be2a50d1fc0a275ff59e9a9e3c2b76e5c8b222d8

See more details on using hashes here.

File details

Details for the file aldakit-0.2.1-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for aldakit-0.2.1-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 3551d5c6a3d6d7a863e0311ef698a5c400f370ef3aba9c8ecb7c2b7bf2769826
MD5 5aaab4b705b38b6e2d751f7b3c1f7e64
BLAKE2b-256 90e2e30d8cf67ed738962837910732fb880a418e083ae16a5729fdbede98010e

See more details on using hashes here.

File details

Details for the file aldakit-0.2.1-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for aldakit-0.2.1-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 91035d0af49d1758e69b5d6063e2b62577329352e4697c4f735d26e81ebad9b2
MD5 ebc39d443946f4d571aa37b8f7e67082
BLAKE2b-256 56457dba1ca2a542dddac1c560b4c8ad1c17eff28accc6f65f3bf60085d3c26b

See more details on using hashes here.

File details

Details for the file aldakit-0.2.1-cp310-cp310-macosx_11_0_x86_64.whl.

File metadata

File hashes

Hashes for aldakit-0.2.1-cp310-cp310-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 979fe1c1e75eaeb9905c33dcdabcf7e5adec4d4b252edf0ff43230fbc3644cc1
MD5 9d683390a2488f4bb7a8500be2a30518
BLAKE2b-256 a4f4c3eeac4f8f9075bf6fb181118f17395d111d092106a9f54a92f296ad56ec

See more details on using hashes here.

File details

Details for the file aldakit-0.2.1-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for aldakit-0.2.1-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 eb703f115e3bbe4d82d7ea06e519c21bc6b1d12bf11fee4ba27ce77b31c7a947
MD5 0ac167a99f84c3a55c06311ddf537bce
BLAKE2b-256 da41493f6442634ede21422c822c8c760329f2e6a20abd831f6da26c1cad1fc4

See more details on using hashes here.

Release history Release notifications | RSS feed

0.4.0

26 files

0.3.1

26 files

This release

0.2.1 This release

26 files

0.2.0

26 files

0.1.10

26 files

0.1.9

26 files

0.1.8

26 files

0.1.7

26 files

0.1.6

31 files

0.1.5

26 files

0.1.4

6 files

0.1.3

6 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page