Open source. Actively evolving. ↗

Osprey.
Logic, in flight.

Effects and handlers. Inferred types.

Declare what your code needs with effects. Supply it once with a handler, wherever the request happens in the call chain.

save-draft.osp
effect Drafts { save: fn(string, string) -> Result<int, Error> }
fn saveDraft(path, text) = match perform Drafts.save(path, text) {
    Success _ => "Saved"
    Error { message } => "Retry: ${message}"
}
fn onSave() = saveDraft("draft.txt", "Ship it.")

let disk = handler Drafts {
    save path text => writeFile(path, text)
}

print(disk(onSave))
SavedOUTPUT

Three syntax flavors: three ways to write Osprey.

INFERRED TYPESEXPLICIT EFFECTSCOMPILED WITH LLVMOpen source. MIT licensed. ↗

01 / Get started

Install Osprey.

Run a program locally, or try the hosted Playground.

Start in your browser

Explore the language without installing anything.

Open Playground ↗

macOS / Linux

brew install nimblesite/tap/osprey

Windows

scoop bucket add nimblesite https://github.com/Nimblesite/scoop-bucket
scoop install osprey

Native compilation requires clang (LLVM 15+). Installation guide → · Contribute on GitHub ↗

02 / Operations and handlers

Effects
with typed handlers.

effect declares an operation’s arguments and result type. perform requests the operation; a handler supplies the implementation.

Choose storage once: disk(onSave) supplies it for onSave and the saveDraft helper it calls. Neither function takes a storage object. Replace the handler in a test to simulate a failure; the application logic stays the same.

The compiler checks operation types and rejects requests without a matching handler, including requests made through helper functions.

See effect and handler syntax ↗
Watch the walkthrough: real storage and a simulated failure using the same function. Run the example →

Osprey is actively evolving. Native control effects support single-shot resumption; full scoped effect rows and reusable continuations remain in development. Current support →

03 / Types and effects

Inferred types.
Checked effects.

Inferred static types

Inferred static types, immutable data, and exhaustive pattern matching. Expected failures remain visible as Result values.

Explore the type system ↗

Three syntax flavors. One language.

A syntax flavor is a way to write the same Osprey language: Default uses braces, ML uses indentation, and Python flavor uses Python-style syntax. Choose per file and import across flavors; all share one type system, effects and compiler.

Compare the syntax flavors ↗

Native fibers and channels

Native fibers and channels keep concurrent work in ordinary functions. Choose the default allocator, tracing GC, or reference counting for your native build.

Follow the fibers ↗

Arithmetic with a stated policy

On the host, an Arith handler supplies the integer overflow policy. Wrapping and saturating helpers state their behavior in the call.

See arithmetic effects ↗

04 / Deployment targets

Deploy to desktop,
web and mobile.

Compile native programs for macOS, Linux and Windows, WebAssembly for browsers and WASI, or shared application logic for iOS and Android.

Build for the capabilities of your target. Unsupported dynamic control effects are rejected on WebAssembly and mobile.

Real measurements, open benchmarks ↗

05 / Python flavor and tensor handlers

Port your Python.
Choose CPU or GPU handlers.

Keep def, lambda, and f-strings. Port computation into Osprey’s Python syntax flavor with inferred types and checked effects. Keep Python libraries through explicit interop.

GPT-2 is the worked port: one Tensor effect, a CPU handler, and a GPU handler using Metal or OpenCL. The handler decides where the arithmetic runs.

Port with Python flavor ↗
examples/gpt2/python/model.pyPython flavor
# osprey: flavor=python
def product(a, b, rows, inner, cols):
    """a [rows, inner] times b [inner, cols]; the handler aborts on failed work."""
    return perform(Tensor.mat_mul(a, b, rows, inner, cols))
make gpt2 FLAVOR=python BACKEND=gpuTRY IT

Python flavor is Osprey source; porting requires adapting Python’s dynamic behavior. Shared tensor storage across Python interop is planned. GPU kernels are not fused; speed depends on the workload and backend. Measurements and source →

06 / Shared modules, native hosts

Shared Osprey modules.
Native UI.

Issue Inbox puts its model, updates, UI layout, GitHub decoding, and SQLite commands in shared Osprey modules. SwiftUI and Android widgets render the application.

  • Browse and search GitHub issues
  • Save issues, notes, and priorities
  • Restore your inbox from SQLite

Actual simulator and emulator captures. Also verified on a physical iPhone. Native hosts provide rendering, SQLite, HTTPS, and lifecycle services.

07 / Community

Build Osprey
with us.

Ask questions, share what you are building, and talk language design with the people making Osprey.