A small systems language.
Safe memory, real concurrency, inline asm.

Native binaries through a portable C backend. Stdlib, toolchain, and LSP all in the box.

v0.1 — self-hosted compiler, native targets via Zig.

hello.glide
import stdlib::http::*;

fn handle(req: *HttpRequest) -> HttpResponse {
    if req.path.eq("/") {
        return HttpResponse::ok().body("hello!\n");
    }
    return HttpResponse::not_found();
}

fn main() -> int {
    http_listen(8080, handle);
    return 0;
}

This page is served by a Glide program close to the one above — TLS terminated by the binary itself.

See it in action

A worker pool, in 18 lines.

Channels, spawn, and errors-as-values compose without ceremony. No async runtime to choose, no Result<T,E> to import — just shapes the language already gives you.

workers.glide
fn process(n: int) -> !int {
    if n < 0 { return err("negative: ${n}"); }
    return ok(n * n);
}

fn worker(jobs: chan<int>, out: chan<!int>) {
    while let n = jobs.recv() {
        out.send(process(n));
    }
}

fn main() -> int {
    let jobs: chan<int>  = make_chan(8);
    let out:  chan<!int> = make_chan(8);

    for _ in 0..4 { spawn worker(jobs, out); }
    for n in [1, 2, -3, 4, 5] { jobs.send(n); }
    jobs.close();

    let mut seen: int = 0;
    while seen < 5 {
        let r: !int = out.recv();
        if r.ok { println!("squared:", r.val); }
        else    { println!("skip:", r.err); }
        seen = seen + 1;
    }
    return 0;
}
  • chan<T> Typed, buffered channels — no shared mutable state.
  • spawn M:N coroutines, scheduled by the runtime. spawn_thread when you need OS threads.
  • !T Either a value or an error. ? propagates, fields read like data.
  • "${n}" String interpolation built into the language.
Why Glide

Six things Glide gets right.

Each idea below replaces a piece of pain you've probably written around in another language. The whole language fits in your head — and these are most of it.

&T

Borrows without lifetimes

Scope-bound borrows (&T, &mut T) catch dangling references, aliased mutation, and use-after-free at compile time. You never write 'a, 'b, or 'static. For owned heap objects there's *T with auto-drop at scope exit, plus defer and defer_err for arbitrary cleanups.

memory.glide
fn draw() {
    let p: *Point = Point { x: 1, y: 2 };
    render(p);
}                                  // freed at scope exit

fn parse_tree() {
    let arena: *Arena = Arena::new(4096);
    defer arena.free();
    let n1: *Node = arena.create(Node);
    let n2: *Node = arena.create(Node);
}                                  // arena freed in one shot
!T

Errors as values

!T is a result; ?T is an option; ?!T is the combined form. The postfix ? operator propagates failures; ?? is the coalesce operator. No exceptions, no Result<T, Box<dyn Error>>, no panic handlers.

errors.glide
fn parse(n: int) -> !int {
    if n < 0 { return err("negative"); }
    return ok(n * 2);
}

fn pipeline(n: int) -> !int {
    let v: int = parse(n)?;
    return ok(v + 1);
}
chan<T>

Real concurrency, no callbacks

M:N coroutines via spawn. Typed channels via chan<T>. The select! macro multiplexes over channel operations with optional default and close-aware arms. Need a kernel thread? spawn_thread. Shared-nothing by design.

concurrency.glide
fn worker(c: chan<int>) {
    c.send(42);
}

fn main() -> int {
    let c: chan<int> = make_chan(1);
    spawn worker(c);
    return c.recv();
}
<T>

Generics + traits

Generics are monomorphised — one C fn per concrete T. Bounds use T: Trait + Trait. Traits support default method bodies and supertraits; *dyn Trait dispatches through a vtable for heterogeneous collections.

traits.glide
trait Render { fn render(self: *Self) -> string; }

impl Render for Box    { fn render(self: *Box)    -> string { return "Box"; } }
impl Render for Circle { fn render(self: *Circle) -> string { return "Circle"; } }

fn show(r: *dyn Render) { println!(r.render()); }
@derive

Metaprogramming, in the language

macro_rules!-style declarative macros with matchers ($x:expr, $x:ident, $x:ty) and the variadic form $($x:expr),*. Procedural macros — @derive(Name), @attr(...), @name!(args) — run in the compiler at expansion time via an embedded interpreter, manipulating the same AST nodes the compiler uses internally. No separate plugin toolchain.

meta.glide
@derive(JsonBind)
struct User { name: string, age: int }

macro_rules! sum {
    ($($x:expr),*) => { {
        let mut t: int = 0;
        $( t = t + $x; )*
        t
    } };
}

let total: int = sum!(1, 2, 3, 4);   // 10
asm

Low-level controls when you need them

Inline assembly with GCC-style operand constraints. naked fn drops the prologue/epilogue so you can lay down your own calling convention. c_raw! { … } injects literal C; @cfg("posix" | "windows") gates declarations per platform. The escape hatches don't compromise the safe defaults — they're explicit, local, and visible at the call site.

tsc.glide
fn read_tsc() -> u64 {
    let lo: u32 = 0;
    let hi: u32 = 0;
    asm volatile { "rdtsc" : "=a"(lo), "=d"(hi) }
    return ((hi as u64) << 32) | (lo as u64);
}
Bundled with the compiler

The standard library is the platform.

No crates.io-style bootstrap. The pieces you reach for every day — HTTP, TLS, JSON, channels, crypto — ship inside the toolchain. One install, one import.

Tooling

One binary. Everything you need.

Package manager, documentation generator, test runner, benchmarker, formatter, LSP — all the same glide command.

pkg

Package manager

glide new, glide add, glide fetch, glide update, glide install. Path deps + git deps (GitHub tarball fast-path, git-clone fallback for the rest). Minimum-version selection across the dep graph; SHA-256-locked cache.

~ shell
$ glide new my_app
$ cd my_app
$ glide add http_x github.com/glide-lang/http_x v0.3.1
$ glide run
doc

Documentation generator

glide doc emits static HTML straight from /// comments. --serve runs a local preview server; --ai additionally drops an AGENTS.md file and a flat llms.txt summary intended for AI ingestion.

~ shell
$ glide doc --serve=8080
$ glide doc --ai --stdlib
doc: wrote 56 modules / 336 items -> ./build/doc/index.html
doc: wrote LLM-friendly summary -> ./build/doc/llms.txt
test

Test + bench runners

glide test discovers *_test.glide files and runs every fn test_* inside them; --golden does stdout diffing. glide bench auto-tunes iteration counts and reports ns/op.

~ shell
$ glide test
PASS test_parse_negative                  0.3ms
PASS test_pipeline_propagates             0.4ms
2 passed, 0 failed

$ glide bench src/hash_bench.glide
bench_sha256_1kb       8421 ns/op
lsp

LSP server, editors first-class

glide lsp talks LSP on stdio: hover, completion, goto-definition (locals, params, fns, structs, enums, traits, macros, proc-macros, fields, import segments), references, rename, formatting — indexed across stdlib + dependencies. Tree-sitter grammar, Zed extension, VS Code extension all live in the repo.

~ shell
$ glide lsp                  # stdio LSP server

# in your editor:
# - hover any symbol -> doc + signature
# - F12 on a stdlib fn -> jumps into source
# - rename refactors across the dep graph

Install

Per-user install — no admin rights needed. Open a new shell once the installer finishes; glide --version should print the installed version.

Linux / macOS

$ curl -fsSL glide-lang.org/install.sh | bash

Windows (PowerShell)

> iwr glide-lang.org/install.ps1 -UseB | iex

Quick start

Scaffold a project

$ glide new my_app
$ cd my_app
$ glide run                  # build + run from manifest

Or a library

$ glide new my_lib --lib     # no `bin`, src/lib.glide
$ cd my_lib
$ glide test

Project layout

my_app/
├── glide.glide       # manifest: name, version, bin, deps
├── src/
│   └── main.glide
├── build/            # compiler output (auto-managed, gitignored)
├── glide_modules/    # fetched / linked dependencies
└── glide.lock        # resolved revs + content hashes

Build from source

The compiler is written in Glide and ships a C seed that compiles to a bootstrap binary; from there Glide builds itself.

$ git clone https://github.com/glide-lang/Glide.git
$ cd Glide

# POSIX
$ cc bootstrap/seed/bootstrap.c -o glide_seed -O2 -lpthread -lm

# Windows hosts need -lws2_32 for the socket builtins
$ cc bootstrap/seed/bootstrap.c -o glide_seed -O2 -lpthread -lm -lws2_32

$ bash tools/install_toolchain.sh             # fetch bundled C toolchain
$ ./glide_seed build bootstrap/main.glide -o glide
$ ./glide install .                           # into ~/.glide/bin

Cross-compile via --target=<triple> — any target the bundled C toolchain supports: x86_64-linux-{gnu,musl}, aarch64-linux-{gnu,musl}, x86_64-windows-{gnu,msvc}, aarch64-macos, riscv64-linux-musl, and more.