A statically-typed, functional language with Python aesthetics that compiles to single binaries.
Status: π§ In active development - Gate D complete, 484 tests passing, release packaging/benchmark publishing in CI, and a new Justfile 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. No runtime dependencies, no crashes, predictable behavior.
# 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 included - Everything you need is built-in: actors, databases, HTTP, CLI tools, TUI. Like Bun, but compiled.
| 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, no runtime dependencies |
β 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 - Helpful diagnostics - snippets, notes, and fix hints in CLI workflows
- Reproducible quality gates -
just check(ormake check), fuzz smoke, perf budgets, release policy checks
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:
- β
484/484 tests passing in local
make 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)
- 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
Replace your infrastructure:
# No Redis, no RabbitMQ, no separate database
fn main() -> Result[(), Error]:
let db = sql.open("app.db")? # Embedded database
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[(), Error]:
let data = read_file("data.csv")?
let processed = process(data)?
write_file("output.csv", processed)?
Ok(())
# 600KB binary, <5ms startup
Dependencies (for building the compiler):
# macOS
brew install bdw-gc
# Ubuntu/Debian
apt install libgc-dev
# Fedora
dnf install gc-develNote: QBE is embedded in the compiler - no external
qbebinary needed. Boehm GC is statically linked into compiled programs. The fern binary and compiled programs are fully standalone - no runtime dependencies, just like Go.
Preferred task runner (Justfile):
just debug
just test
just check
just release-package
just benchmark-reportJustfile is the primary developer entrypoint and delegates to the existing Makefile backend.
Direct Make targets (still supported):
make # Debug build (default)
make debug # Debug build with symbols
make release # Optimized release build
make test # Run test suite
make check # Build + tests + examples + strict style checks
make style # Check FERN_STYLE compliance only
make release-package # Build + package release bundle into dist/
make benchmark-report # Publish reproducible benchmark + case-study reportFern 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
make test
# Check style compliance
make style
# See current progress
cat ROADMAP.md