The safety of a strict type system, the speed of native code and a small, familiar syntax. Run programs on the interpreter while you work, then compile them to a single executable with LLVM.

fn main() {
    let names = ["Ada", "Grace", "Linus"]
    for name in names {
        print(f"Hello, {name}!")
    }
}

Reliable by design

Brim has no null and no exceptions. A value that may be missing is an Option, and a function that can fail returns a Result that the caller has to handle.

The ? operator passes an error up in one character, and integer overflow stops the program instead of producing a wrong number.

fn parse_port(text: string) -> Result[i64, string] {
    let port = match text.parse_int() {
        Some(n) => n
        None => return Err(f"not a number: {text}")
    }
    if port < 1 || port > 65535 {
        return Err(f"out of range: {port}")
    }
    return Ok(port)
}

Ready when you are

One brim command creates projects, runs tests, formats code, writes documentation and builds native executables for Linux, macOS and Windows.

Dependencies come from the package registry, a directory or a git repository, and brim.lock keeps every build the same.

$ brim new shop
created project `shop` in shop
$ cd shop
$ brim test
running 1 test
test test_greeting ... ok

test result: ok. 1 passed; 0 failed
$ brim build
built target/shop
$ ./target/shop
Hello, world!

Here to help

Every match must handle every case, so adding a variant to an enum shows each place that needs an update.

Compiler messages point to the code, explain what is wrong and suggest a fix. Editors show the same messages through the Brim language server.

error[E0229]: `match` does not cover every value
 --> pay.brim:8:11
  |
8 |     match payment {
  |           ^^^^^^^ some values have no matching arm
  |
  = note: not covered: `Cash`
  = help: add an arm for each, or a `_ => ...` arm

Built for services

The standard library comes with an HTTP server and client, JSON, PostgreSQL, logging and files, so a service needs no framework to get started.

Write an API as plain functions and brim gen ts --angular generates the TypeScript types and an Angular client to call it.

import std.http
import std.log

fn serve(port: i64) -> Result[bool, string] {
    let server = http.serve("127.0.0.1", port)?
    log.info(f"listening on port {port}")
    loop {
        let request = server.next()?
        let body = f"Hello from {request.path}"
        request.respond(http.text(200, body))?
    }
}

News

The package registry is live

Brim packages now have a home at registry.brimlang.com. Add a package to brim.toml by version and brim resolves it, downloads it and records the exact version in brim.lock.

Publishing your own package is brim login and brim publish.

Read how it works

Ready to try Brim?

Install Brim on macOS, Linux or Windows and write your first program in a minute.

curl -fsSL https://brimlang.com/install.sh | sh
Get started