Systems Language ·

Write fast.
Burn clean.

Ash is a minimalist, statically-typed systems language. Write readable code, compile to C, run native binaries — with a single dependency.

stars
🍴 forks
🐛 open issues
📦 releases
fibonacci.ash
fn fib(n: int): int {
    if n <= 1 { return n }
    return fib(n - 1) + fib(n - 2)
}

fn main() {
    for i in 0..10 {
        print("fib(", i, ") =", fib(i))
    }
}
structs.ash
struct Person {
    name: string
    age:  int
}

enum Status {
    Active,
    Inactive,
}

fn greet(p: Person): string {
    return "Hello, " + p.name
}

fn main() {
    alice := Person{ name: "Alice", age: 30 }
    print(greet(alice))
}

Everything you need.
Nothing you don't.

Native performance
Compiles to optimized C via zig cc. No VM, no GC, no overhead. The output is a lean native binary.
🔥
One dependency
Zig is all you need. It builds the compiler and compiles your programs via zig cc — on Linux, macOS, and Windows.
📐
Clean syntax
Type inference, multi-return functions, structs, enums, and switch — all with a syntax that reads like prose.
🧠
Static types
Full static type checking with inference. Errors are caught at compile time with precise file:line:col messages.
📦
Standard library
io, string, math, and os modules ship with the runtime. Import what you need, ignore what you don't.
🔍
Readable codegen
The generated C is clean and human-readable. Inspect it any time at /tmp/ash_*.c.

Compilation pipeline

Source
.ash file
Lexer
Token stream
Parser
AST
Semantic
Type check + resolve
C Codegen
Clean C99
zig cc
Native binary

Install

One dependency. Three platforms. Five minutes.

Previous releases

All releases on GitHub →
After installing
1
Verify Zig is installed
Ash requires Zig 0.15+. Download Zig →
zig version
# 0.15.0 or later
2
Restart your terminal
Source your shell config so the PATH change takes effect.
source ~/.bashrc
ash version # should print: ...
3
Create your first project
ash init
ash run main.ash
4
Build a standalone binary
ash build main.ash
./main

Introduction

Ash is a minimalist, statically-typed systems language that compiles to C via zig cc. It runs five phases — lexing, parsing, semantic analysis, C codegen, and zig cc — entirely in memory before producing a native binary.

Why zig cc?

Building a custom machine-code backend requires instruction selection, register allocation, and platform ABI handling for every target. Ash skips all that by emitting clean C99, then delegating to zig cc — a battle-tested LLVM-based compiler that ships as a single binary alongside Zig. Because Ash already requires Zig, every user has zig cc for free.

Quick start

ash init           # create main.ash
ash run main.ash   # compile + run
ash build main.ash # compile to binary

Hello World

Every Ash program has a main function. print is always available without an import.

fn main() {
    print("Hello, World!")
}
ash run hello.ash
# Hello, World!

Variables

Use := for inferred declaration, explicit annotation with name: type = value, or const for immutables.

// Inferred
x := 10
name := "Ash"
flag := true

// Explicit
count: int = 0
ratio: float = 3.14

// Constants
const MAX = 100
const LIMIT: int = 50

x += 5
x -= 2

Types

AshCNotes
intint64_t64-bit signed integer
floatdouble64-bit IEEE 754
boolinttrue = 1, false = 0
stringconst char*UTF-8, null-terminated

Functions

Functions can be defined in any order — a forward-declaration pass runs first.

fn add(a: int, b: int): int {
    return a + b
}

Multiple return values

fn divmod(a: int, b: int): (int, int) {
    return a / b, a % b
}

q, r := divmod(17, 5)

Control Flow

if / else

if x > 0 { print("positive") }
else if x == 0 { print("zero") }
else { print("negative") }

for · while · break · continue

for i in 0..5 { print(i) }

a := [10, 20, 30]
for n in a { print(n) }

i := 0
while i < 10 {
    i += 1
    if i == 3 { continue }
    if i == 6 { break }
    print(i)
}

switch

switch lang {
    case "ash" => print("Ash!")
    default   => print("unknown")
}

Arrays & Vecs

Dynamic array

a := [10, 20, 30]
push(a, 40)
last := pop(a)
print(len(a), a[0])

Fixed array

b := ![1, 2, 3, 4, 5]
b[2] = 77
for i in 0..5 { print(b[i]) }

Structs

struct Point { x: int; y: int }

p := Point{ x: 10, y: 20 }
print(p.x, p.y)
p.x = 99

Enums

enum Direction { North, South, East, West, }

dir := Direction.North
print(dir)

io

import io
name    := io.input("Enter your name: ")
io.write_file("out.txt", "Hello, " + name)
content := io.read_file("out.txt")
print(content)

string

import string
s := "Hello, Ash!"
print(str_upper(s))            // "HELLO, ASH!"
print(str_slice(s, 0, 5))      // "Hello"
print(str_contains(s, "Ash")) // 1
n := parse_int("123")          // 123

math

import math
print(sqrt(16.0))        // 4.0
print(abs(-42))          // 42
print(clamp(15, 0, 10))  // 10
print(sin(0.0))          // 0.0

os

import os
print(argc())
home := getenv("HOME")
print("HOME:", home)

Source

Every release pulled live from GitHub. Stars, commits, and contributors update automatically.

 stars
🍴 forks
👁 watching
🐛 open issues
📦 releases
View on GitHub →
Release history

Latest activity on main

Source code

Ash is open source under the MIT license. The compiler is written in Zig. Contributions, bug reports, and feature requests are welcome on GitHub.

View on GitHub →

Community

Ash is built in the open. Everyone is welcome.

 stars
👥 contributors
🐛 open issues
🔀 open PRs
🐙
GitHub
Browse the source, open issues, submit pull requests. All development happens here.
Source of truth
💬
Discussions
Ask questions, share projects, discuss language design. Loading…
Q&A · Ideas
🐛
Issue Tracker
Report bugs, request features. Loading…
Bugs · Features
📮
Newsletter
Occasional updates on new releases, language changes, and community projects. Low volume, high signal.
Coming soon

What people are talking about

People who built Ash

Fix a bug
Look for issues labelled good first issue on GitHub.
Write examples
Add .ash programs to examples/ that show interesting patterns.
Improve docs
Fix typos, clarify confusing sections, or write new guides.

Support

Stuck? Here's where to start.

The compiler looks for ash_runtime.c relative to its own executable. Make sure ash is inside a bin/ folder next to a runtime/ folder. Re-run install.sh to fix the layout.
Ash uses zig cc to compile programs. Install Zig 0.15+ from ziglang.org/download and make sure it's in your PATH.
Pull latest with git pull, then re-run install.sh or install.bat. The installer overwrites the old binary and runtime files.
macOS may quarantine locally-built binaries. Run xattr -d com.apple.quarantine ./yourprogram or allow it in System Preferences → Security & Privacy.
No. zig cc is the C compiler Ash invokes. It is not optional. Zig is a single downloadable binary — installation takes under a minute.
During ash run, the generated C is written to /tmp/ash_main.c (Unix) or %TEMP%\ash_main.c (Windows). It is clean, human-readable C99.
Open an issue on GitHub. Include your Ash version (ash version), Zig version (zig version), OS, and the smallest .ash file that reproduces the problem.

Latest from the tracker

Still stuck?

Open a discussion on GitHub. Describe what you expected, what happened, and include your platform and Ash version.

Open a Discussion →