Quick Start
Get up and running with Flow in minutes.
Install (recommended)
Flow ships as a prebuilt self-contained binary — no .NET SDK needed on the install side.
# Per-user install — no sudo required
curl -fsSL https://raw.githubusercontent.com/NoahFreelove/flow-sharp/main/scripts/install.sh | bash This drops the runtime at ~/.local/share/flow/ and symlinks flow into ~/.local/bin/. Add ~/.local/bin to $PATH if it isn’t already.
For a system-wide install (writes to /usr/local/, may require sudo):
./scripts/install.sh --system scripts/install.sh -h lists every flag.
Build from source (optional)
If you want to hack on the interpreter itself, you’ll need the .NET 10 SDK.
git clone https://github.com/NoahFreelove/flow-sharp
cd flow-sharp
dotnet build Run a Script
Create a file called hello.flow:
use "@std"
(print "Hello, Flow!")
Int x = 5
Int y = 10
Int sum = (add x y)
(print $"Sum: {sum}")Open in playgroundRun it:
flow run hello.flow
# or, from a source build:
dotnet run --project flow-interpreter hello.flow Start the REPL
flow repl The REPL auto-imports @std, @audio, and @collections. Type Flow expressions interactively and see results immediately. Use :help, :clear, :stop, or :quit for built-in commands. In a real terminal it supports Tab completion (LSP-backed), Ctrl+R reverse history search, and PrettyPrompt editing; persistent history is stored at ~/.config/flow/history. Piped or redirected stdin falls back to the legacy line reader (CI-safe).
Watch Mode
Automatically re-render a script when the file changes — reloads quantize to the next bar boundary with a 64-sample crossfade so playback never glitches. The terminal shows a four-row live status panel with tempo/bar, active blocks, voice usage, and sticky advisories.
flow watch path/to/script.flow See Live Coding for live { } blocks, the flow watch status panel, and the determinism trade-off.
Evaluate an Expression
flow eval 'Int x = 5; (print (str x))' Your First Melody
Create melody.flow:
use "@std"
use "@audio"
tempo 120 {
timesig 4/4 {
key Cmajor {
section intro {
Sequence melody = | C4 E4 G4 C5 |
}
Song song = [intro]
Buffer buf = (renderSong song "piano")
(exportWav buf "melody.wav")
(print "Exported melody.wav!")
}
}
}Open in playgroundflow run melody.flow This renders a simple C major arpeggio using the (sample-based) piano and exports it as a WAV file.
A Taste of Newer Features
Tuples, dicts, symbols, named args, and pattern matching all land in the core language:
use "@std"
Note: tuple + destructuring
<<Int x, Int y>> = <<3, 4>>
(print $"x={x} y={y}")
Note: dict + named-arg friendly builtins
Dict<Symbol, Int> bpms = (dict #verse 120 #chorus 140)
Int v = (getOr bpms #bridge 100)
Note: pattern matching with music-aware extractors
String label = (match Cmaj7
| Cmaj7 => "tonic"
| Dm => "ii"
| _ => "other")
(print label)Open in playgroundStandalone Flow Editor (Optional)
A desktop GUI for editing and running Flow scripts is included in the repo as flow-editor:
dotnet run --project flow-editor This is optional — everything in the language is usable from the CLI.
Important: The Standard Library
Most Flow programs need to start with:
use "@std"Open in playgroundThis imports the core standard library, which provides essentials like print, str, concat, add, sub, mul, div, list, dict, map, filter, and many more. @std transitively pulls in @collections and @bars.
For audio features, also import:
use "@audio"Open in playgroundOther opt-in modules: @notation, @composition, @sfz, @patterns, @generative, @improv, @notation-io, @test. See Imports and Modules for the full list and what each one unlocks.
Running Tests
Flow now ships a pure-Flow test framework via @test:
# Run every test_*.flow file under tests/
flow test tests/
# Run a single test file
flow test tests/test_comprehensive.flow A test file uses (test "name" body), (assert), (assertEq), and (assertWithinDb). Each test gets a hermetic snapshot/restore of mutable engine state so cases don’t bleed into each other.
The legacy “run-the-script-and-check-exit-code” pattern still works:
# Run all legacy .flow test scripts
for test in tests/test_*.flow; do flow run "$test"; done See Also
- Language Basics - Variables, tuples, dicts, pattern matching, comments
- Note Streams - Write music inline
- Loops -
for,while,break,continue - String Interpolation -
$"..."syntax - Imports and Modules - All 15 stdlib modules
- Examples - Complete working programs