A statically-typed, functional language with Python aesthetics that compiles to single binaries.
Status: π§ In active development - Gate D complete, 534 tests passing, release packaging/benchmark publishing in CI, and Justfile as the primary task runner
Fern is a programming language designed to make both fast CLI tools (<1 MB) and full-stack applications (2-4 MB) with the same elegant syntax. Compiler outputs are standalone and behavior is designed to stay predictable.
# Clean, readable syntax with explicit error handling
let content = read_file("config.txt")?
let config = parse_config(content)?
let validated = validate(config)?
Ok(process(validated))
Fern should spark joy - for those familiar with functional programming, writing Fern should feel delightful, not tedious.
One obvious way - There should be one clear, idiomatic way to accomplish any task. No agonizing over which of five approaches to use.
No surprises - The language actively prevents the bugs that waste your afternoon. If it compiles, it probably works.
Jetpack surface included - Core modules ship with the compiler; SQL now has a concrete SQLite runtime backend, and HTTP GET/POST calls are backed by the civetweb runtime client.
| Principle | How Fern Delivers |
|---|---|
| Readable | Python-like indentation, no braces, clear keywords |
| Functional | Immutable by default, pure functions, pattern matching |
| Safe | No null, no exceptions, no panics - only Result/Option types |
| Predictable | Explicit error handling, no hidden control flow, exhaustive matching |
| Fast | Compiles to native code, ~35x faster than Python |
| Portable | Single-binary distribution with embedded toolchain/runtime |
β NullPointerException β Option type, exhaustive matching
β Unhandled exceptions β Result type, must handle errors
β Race conditions β Actors with isolated heaps, no shared state
β "It works on my machine" β Single binary, all dependencies included
β Silent failures β Compiler enforces error handling
β Action at a distance β Immutability prevents spooky mutation
- Static types with inference - safety without verbosity
- Pattern matching - exhaustiveness checking catches bugs
- Garbage collected runtime - Boehm-backed runtime plus Perceus baseline ownership primitives
- Language tooling - LSP with diagnostics, hover, definition, completion, rename, and code actions
- Stable stdlib API surface -
fs,http,json,sql,actors, andFilealias compatibility - Explicit runtime readiness - SQL is SQLite-backed today; HTTP GET/POST are runtime-backed for
http://andhttps://URLs with deterministicErr(FERN_ERR_IO)on invalid URLs/network failures - Helpful diagnostics - snippets, notes, and fix hints in CLI workflows
- Reproducible quality gates -
just check, fuzz smoke, perf budgets, release policy checks
Canonical module naming in docs/examples:
String,List,System,Regex,Result,Option, andTui.*fs,json,http,sql, andactorsFile.*remains supported as a compatibility alias forfs.*
Fern is implemented with strict TDD. See DESIGN.md for language details and ROADMAP.md for gate-by-gate status.
Execution gates:
- β Gate A (DX + language feel) passed
- β Gate B (reliability + regression resistance) passed
- β Gate C (stdlib/runtime surface quality) passed
- β Gate D (ecosystem/adoption hardening) passed
Recent outcomes:
- β
534/534 tests passing in local
just test - β Cross-platform CI (Ubuntu + macOS) with build/test/style/perf/fuzz/example checks
- β
Release packaging bundles (
fern+libfern_runtime.a+ policy/docs artifacts) - β
Conventional-commit-driven semver + release notes via
release-please - β
Published reproducible benchmark + case-study report in
docs/reports/benchmark-case-studies-2026-02-06.md - β LSP support beyond MVP (completion, rename, code actions, better source positions)
Active focus:
- π§ Post-Gate D stabilization and milestone polish (see ROADMAP.md)
- Documentation Index - Canonical map of project docs
- Language Design - Complete specification
- Implementation Roadmap - Development plan and progress
- Decision Log - Architectural decisions
- Coding Standards - TigerBeetle-inspired style guide
- Development Guidelines - For AI-assisted development
- Compatibility Policy - Upgrade/deprecation guarantees
Fern takes inspiration from the best features of:
- Gleam - Type system, simplicity
- Elixir - Pattern matching, actors, pragmatic design
- Rust -
?operator, Result types - Zig - Comptime, defer, minimalism
- Python - Readability, aesthetics
- Go - Single binary deployment
Full-stack shape (stable API surface, SQL + HTTP runtime backends available):
# No Redis, no RabbitMQ, no separate database
fn main() -> Result((), Int):
let db = sql.open("app.db")? # SQLite-backed runtime handle
let cache = spawn(cache_actor) # In-memory cache (actor)
let queue = spawn(job_queue) # Job queue (actor)
http.serve(8080, handler(db, cache, queue))
# One 3.5MB binary, no external dependencies
CLI tools stay tiny:
# Fast, small, no runtime
fn main() -> Result((), Int):
let data = fs.read("data.csv")?
let processed = process(data)?
fs.write("output.csv", processed)?
Ok(())
# 600KB binary, <5ms startup
Dependencies (for building the compiler):
# macOS
brew install bdw-gc sqlite
# Ubuntu/Debian
apt install libgc-dev libsqlite3-dev
# Fedora
dnf install gc-devel sqlite-develAlso install the task runner:
# macOS
brew install just
# Ubuntu/Debian
apt install just
# Fedora
dnf install justNote: QBE is embedded in the compiler - no external
qbebinary needed. Boehm GC is statically linked into compiled programs. SQL stdlib calls link against SQLite (sqlite3) and HTTP stdlib calls are implemented via vendored civetweb client code in the runtime.
Preferred task runner (Justfile):
just debug
just test
just check
just docs
just docs-check
just release-package
just benchmark-reportJustfile is the primary developer entrypoint for all build and quality tasks.
Fern uses release-please with conventional commits to drive release PRs, semver bumps, and changelog notes automatically.
The initial release baseline is pinned to 0.1.0 (not 1.0.0).
fix:commits trigger patch bumpsfeat:commits trigger minor bumpsfeat!:orBREAKING CHANGE:triggers minor bumps while<1.0.0(and major bumps once>=1.0.0)- Release notes/changelog entries are generated from conventional-commit history
The workflow in .github/workflows/release-please.yml requires RELEASE_PLEASE_TOKEN to be set in repo secrets to open/update release PRs.
Ferns are ancient, resilient plants that have survived for over 350 million years. Like the plant, Fern the language is designed to be:
- Resilient - No crashes, no nulls, explicit error handling
- Elegant - Simple fronds (syntax) that unfold into complex patterns
- Evergreen - Clean fundamentals that age well
Plus, it's short, memorable, and wasn't taken.
The fern emoji (πΏ) is Fern's visual identity. You can even use it as a file extension:
# Both work!
fern build hello.fn
fern build hello.πΏWhy? Because we can, and it makes your file explorer more interesting.
Not yet. Core compiler/runtime/tooling paths are heavily tested and Gate D is complete, but Fern is still pre-1.0 and evolving. See ROADMAP.md and docs/COMPATIBILITY_POLICY.md for current guarantees and planned work.
MIT License - see LICENSE for details.
What this means: You can use Fern for anything (personal, commercial, proprietary) without restrictions. We want Fern to be as widely useful as possible.
We're actively implementing the compiler using AI-assisted test-driven development. See CLAUDE.md for development workflow and guidelines.
# Build and test
just test
# Check style compliance
just style
# See current progress
cat ROADMAP.md