Chapter 01 7 min read

Getting started

Glide is a small systems language: it compiles to a real binary you can ship to a server that doesn't have Glide installed. If you've used Python or JavaScript, Glide will feel different in one big way: there's no interpreter watching your code as it runs. Your program is translated into machine instructions once (we call that compiling), and then the machine instructions are what runs. That's why Glide programs can be small, fast, and don't need anything else installed to run.

The toolchain is one binary (glide) and projects are described by a single struct in a file called glide.glide. That's about it for the infrastructure — we'll get to writing code in two minutes.

Install

On macOS and Linux, paste this into your terminal:

shell
curl -fsSL https://glide-lang.org/install.sh | bash

On Windows, open PowerShell and paste this:

shell
iwr -useb https://glide-lang.org/install.ps1 | iex

The installer drops a single executable at ~/.glide/bin/glide and prints the line you need to add to your shell's PATH. Restart your terminal, then check:

shell
glide version

You should see glide 0.3.3 or newer.

Your first program

Create a file called hello.glide with this content:

hello.glide
fn main() -> i32 {
    println!("hello, glide");
    return 0;
}

Now run it:

shell
glide run hello.glide

You should see hello, glide printed. That's it — you wrote, compiled, and ran a Glide program.

Let's look at the four pieces of that snippet, because they all carry meaning you'll see in every Glide file:

  • `fn main()`fn declares a function. main is the name the toolchain looks for when you run a program: it's the entry point, the place execution starts.
  • `-> i32` — the function returns a value of type i32 (a 32-bit integer). For main, the return value becomes the program's exit code: 0 means success, anything else means failure. (Try return 1; and run the file again — glide run will exit with a non-zero status.)
  • `println!(...)`println! writes a line to stdout. The ! at the end is part of the name; it tells you this is a macro (a feature that does compile-time text manipulation). For now just treat it as "the print function."
  • `return 0;` — every statement ends with ;. The return is mandatory — Glide doesn't infer a return value from the last expression like some languages do.

A real project

A single file is fine for a script, but once you're past a hundred lines you'll want a project. glide new scaffolds one for you:

shell
glide new hello
cd hello

That creates this layout:

output
hello/
  glide.glide        the manifest — name, version, deps, build target
  src/
    main.glide       fn main() lives here
  .gitignore

Now look at glide.glide. It's not a YAML or JSON config file — it's Glide source code, declaring one variable named manifest of type Package:

glide.glide
let manifest: Package = Package {
    name:        "hello",
    version:     "0.1.0",
    description: "",
    author:      "",
    license:     "",
    repository:  "",
    bin:         "src/main.glide",
    deps: vec_of(
    ),
};

The CLI never compiles this file — it reads the literal fields out of it. The reason it's still Glide syntax (rather than YAML) is that you can edit it with all your normal tools (LSP completion, syntax highlight, etc.) and the structure is the same as everything else in the language.

From inside the project directory, the commands don't need a file argument — they pick up bin: "src/main.glide" from the manifest:

shell
glide run       # compiles + runs src/main.glide
glide build     # compiles to ./build/hello.exe (or ./build/hello on Linux/macOS)
glide check     # type-checks without compiling — fast feedback for your editor

The four commands you'll use every day

Every CLI has dozens of options. These four cover most of an actual day of writing Glide:

  • `glide run` — compile and execute. The default while writing code. Pass a file path (glide run foo.glide) for one-offs, or just glide run inside a project.
  • `glide build` — compile and stop. Pass --release for the optimized build that goes to production. Pass --target=x86_64-linux-gnu (or aarch64-apple-darwin, or x86_64-windows-gnu) to cross-compile for another OS without leaving your machine.
  • `glide check` — type-check only, no machine code generated. Used by editors and CI. Fast: it can tell you about a type mismatch in milliseconds.
  • `glide new <name>` — scaffold a fresh project. Use glide new <name> --lib if you're starting a library others will depend on.

Two more you'll meet in Modules and packages:

  • `glide add <name> <github.com/user/repo> <rev>` — add an external dependency to glide.glide.
  • `glide fetch` — download the dependencies declared in the manifest into glide_modules/.

What just happened under the hood

When you ran glide run hello.glide, the toolchain went through five stages:

  1. Parse — read the text into a tree (an AST) that represents the program's structure.
  2. Type-check — verify every variable is used at the type it was declared, every function gets the right argument types, and every value lives long enough. This is where most beginner mistakes are caught — at compile time, before the program ever runs.
  3. Emit C — translate the AST into C source code.
  4. Compile C — invoke the system C compiler (cc, clang, or the bundled zig cc).
  5. Run — execute the resulting binary.

You can stop at any step. glide check halts after step 2. glide build --emit-c keeps the generated C in ./build/ if you want to peek. The end-product binary is just a regular native executable — strip it, ship it, run it on a server without Glide installed.

Where to next

You've got a working toolchain and a first program. The rest of the book builds the language up from this point:

  • The next chapter (Types and bindings) is about the values you can store: integers and floats by width, strings, structs, vectors, hashmaps. It's where you'll see Glide's static type system show up for real.
  • After that, Functions and control flow covers if / match / for and how blocks return values.