Installing Osprey
By Christian Findlay · Last verified 25 July 2026
Osprey compiles your program to textual LLVM IR and then hands that IR to
clang to produce and link a native executable. The osprey binary does
not bundle LLVM — it shells out to a clang already on your system. So
installing Osprey is two steps:
- Install the LLVM/clang toolchain (the prerequisite).
- Install the
ospreycompiler.
This is required. The release tarballs and the Homebrew/Scoop packages ship only the
ospreybinary and its C runtime archives — never LLVM itself. Ifclangis not on yourPATH, compiling any program fails with an error likeclang: command not foundorfailed to spawn C compiler. Install the toolchain first.
What Osprey needs
| Task | Required tools |
|---|---|
| Compile & run native programs | clang (a full LLVM clang, 15 or newer) |
| Link the C runtime on Windows | clang plus MinGW gcc |
Compile to WebAssembly (--target=wasm32) |
clang, wasm-ld (from lld), a WASI sysroot |
Debug info (--debug, DWARF line tables) |
LLVM 19 or newer recommended |
Any recent LLVM release works for everyday compilation — there is no exact version to match. When in doubt, install your platform's current LLVM.
macOS
The quickest path uses Apple's bundled clang from the Xcode Command Line Tools, which is enough to compile and run native Osprey programs:
xcode-select --install
For a current, full LLVM (recommended for WebAssembly, debug info, or if you hit an IR-compatibility error with Apple's older clang), install it with Homebrew:
brew install llvm
Homebrew's llvm is keg-only — its clang is deliberately kept off your
PATH so it does not shadow Apple's. Point Osprey at it in one of two ways:
# Option A — put Homebrew LLVM ahead of Apple's clang for this shell:
export PATH="$(brew --prefix llvm)/bin:$PATH"
# Option B — leave PATH alone; tell Osprey which compiler to use per-invocation:
OSPREY_CC="$(brew --prefix llvm)/bin/clang" osprey app.osp --run
Then install the compiler:
brew install nimblesite/tap/osprey
Linux
Install clang, llvm, and (for WebAssembly) lld from your distribution:
# Debian / Ubuntu
sudo apt-get update && sudo apt-get install -y clang llvm lld
# Fedora / RHEL
sudo dnf install -y clang llvm lld
# Arch
sudo pacman -S --needed clang llvm lld
Osprey is distributed for Linux via the Homebrew tap (or the release tarball):
brew install nimblesite/tap/osprey
Windows
Osprey shells out to clang and links the C runtime with MinGW's gcc, so you
need both LLVM and MinGW. Scoop installs them as dependencies of the
osprey package:
scoop bucket add nimblesite https://github.com/Nimblesite/scoop-bucket
scoop install osprey
If you install Osprey another way (e.g. the release tarball), install the toolchain yourself:
scoop install llvm gcc
Alternatively, install the official LLVM release
and a MinGW-w64 toolchain, and make sure both clang.exe and gcc.exe are on
your PATH.
Verify the toolchain
After installing, confirm clang resolves and is a full LLVM clang:
clang --version
Then compile and run a program:
echo 'fn main() = print("Osprey is installed")' > hello.osp
osprey hello.osp --run
You should see Osprey is installed.
Debugging in VS Code
Install the Osprey extension and LLDB, including its lldb-dap executable. Open an .osp or .ospml file, set a breakpoint and press F5. The extension builds a native debug executable and launches LLDB-DAP. If the adapter is outside your PATH, set osprey.debug.lldbDapPath to its full path in VS Code settings.
Breakpoints inside a lambda can inspect its primitive parameters, captures and local bindings, including at the return line of a block containing just one expression. Functions stored in records retain their source names and inspectable arguments. Shared mutable cells show their current values as handlers update them. Effect handler arms expose their parameters and captures, including when they resume a continuation. Extracted GPU kernels running on the host support the same breakpoints and show their captured values. Within a match arm or nested block, the debugger shows its primitive bindings and initialized local values; leaving that scope restores enclosing names. This also works inside closures and effect handlers. A local appears after its initializer finishes. While initializing a shadowing binding, you can still inspect the enclosing value; later declarations stay hidden. This also applies to shared mutable cells. Expand a record to inspect its named fields and nested values. This covers anonymous records, concrete generic records and records replaced in shared cells by handlers. Collections, unions, Results and closures still need dedicated displays; optimized-away value reporting remains unfinished. See the debugger contract for the supported build and source-mapping behavior.
To build a debug executable from the command line:
osprey hello.osp --debug --debug-opt=none --compile --debug-out hello-debug --debug-preserve-ir
This keeps the executable and its generated IR (hello-debug.ll) for inspection. Add "preserveArtifacts": true to a VS Code launch configuration to keep the IR from an editor build, or set "compilerPath" to select a compiler for that launch. Editor launches always build without optimization. Optimized debugging and heap inspection are still planned; unsupported CLI modes report an error.
For programs that read input, add "console": "integratedTerminal" to the launch configuration. "externalTerminal" uses VS Code’s configured external terminal. Both terminal modes require LLDB-DAP 21 or newer; an older or unrecognised adapter produces a clear error. The default "internalConsole" displays output in the Debug Console and does not provide stdin.
The OSPREY_CC override
When several clangs coexist — for example a keg-only Homebrew LLVM, or the MinGW
clang on Windows that must match the MinGW-built runtime archive — set
OSPREY_CC to the exact driver Osprey should invoke instead of the default
clang:
OSPREY_CC=/opt/homebrew/opt/llvm/bin/clang osprey app.osp --run
Troubleshooting
clang: command not found/failed to spawn C compiler— LLVM is not installed, or itsclangis not on yourPATH. Install it (above) or pointOSPREY_CCat a workingclang.- Homebrew says
ospreyis installed but compiling fails — Homebrew'sllvmis keg-only. Add$(brew --prefix llvm)/binto yourPATH, useOSPREY_CC, or install the Xcode Command Line Tools for Apple's clang. - An IR / bitcode version error when compiling — your
clangis older than the IR Osprey emits. Install a current LLVM and select it withPATHorOSPREY_CC. - WebAssembly build can't find
wasm-ld— installlld(brew install lldon macOS, your distro'slldpackage on Linux). See the Web Apps guide for the full Wasm toolchain.
No install required
To try Osprey without any toolchain, use the browser-based Playground — it compiles and runs Osprey entirely in your browser, no LLVM needed.