Systems code that reads like TypeScript
Native binaries with no garbage collector. The same toolchain type-checks and builds the TypeScript you already have.
struct User {
id: int,
name: string,
}
async fn users(): Result<[]User, Error> {
let res = await http.get("/api/users")?
return await res.json()
}
async fn main() {
match await users() {
Ok(list) => print("{list.len()} users"),
Err(e) => print("failed: {e}"),
}
}
// Plain TypeScript, run by the same binary.
import { readFile } from 'node:fs/promises'
interface Config {
host: string
port: number
}
const raw = await readFile('home.json', 'utf8')
const config: Config = JSON.parse(raw)
console.log(`${config.host}:${config.port}`)
# A native binary, with no runtime beside it
home build src/main.home -o app
# The same compiler checks your TypeScript
home tsc --noEmit
# And runs it on Home's own JS runtime
home run server.ts
One compiler, two languages
Home compiles Home. It also parses, type-checks and emits TypeScript, so a mixed codebase needs one toolchain instead of two.
How the TypeScript path worksEvery case, or it does not compile
Exhaustive match over enums, tuples and ranges, with guards and bindings. A missing branch is a compile error, not a runtime surprise.
See pattern matchingMemory without a collector
Ownership and borrowing settle lifetimes at compile time. No pauses, no hand-rolled arenas, no runtime to ship beside the binary.
See the memory modelCompile time is just code
Comptime runs real Home during compilation. Build lookup tables, specialise generics and validate configuration before the binary exists.
See comptimeA Bun and Node compatible runtime, in progress
JavaScript runs through Home's own JavaScriptCore realm rather than a bundled Node. 24 of 47 node modules are callable today, alongside a broad Bun API surface, and the work is tracked module by module in the open.
Follow the runtime portEvery figure is a file-count or row-count measurement against an external baseline, refreshed 2026-07-13. Read how each one is produced.
Your TypeScript already compiles here
Home did not stop at a new language. The same binary that builds .home files runs a full TypeScript front end, checked against the upstream conformance corpus rather than against our own tests.
- Byte-for-byte diagnostics. Errors are compared against baselines generated by the reference compiler, not approximated.
- One command, one config.
home tscreads thetsconfig.jsonyou already have. - Editors keep working.
home lsp --stdiospeaks the protocol your editor already speaks.
# Point the Home compiler at the project you already have
cd my-typescript-app
home tsc --noEmit
# Same diagnostics, same codes, same exit status
# error TS2345: Argument of type 'string' is not
# assignable to parameter of type 'number'.
# Explain any code without leaving the terminal
home explain TS2345
What people build with it
Home targets the places where a runtime is a liability: fixed frame budgets, freestanding binaries, and services that have to start instantly.
From clone to binary
Home builds itself with a Pantry-pinned Zig toolchain, so the setup is two commands and no global installs.
Install the toolchain
Pantry pins the exact Zig version the compiler is built against, inside the project.
git clone https://github.com/home-lang/home.git
cd home && pantry install
./pantry/.bin/zig build
Write a program
Functions, types and string interpolation behave the way you would guess.
// hello.home
fn main() {
let name = "Home"
print("Hello, {name}!")
}
Build and run it
The output is a native executable with nothing to install alongside it.
./zig-out/bin/home build hello.home
./hello
# Hello, Home!
Where Home actually is
The compiler is under active development and the docs say so on every page. Here is the short version, so you can decide what to trust it with.
Try it on something small
A CLI tool, a parser, one service. Half an hour is enough to know whether the language fits your head.