LmCast :: Stay tuned in

Nanolang: A tiny experimental language designed to be targeted by coding LLMs

Recorded: Jan. 20, 2026, 10:03 a.m.

Original Summarized

GitHub - jordanhubbard/nanolang: A tiny experimental language designed to be targeted by coding LLMs

Skip to content

Navigation Menu

Toggle navigation

Sign in

Appearance settings

PlatformAI CODE CREATIONGitHub CopilotWrite better code with AIGitHub SparkBuild and deploy intelligent appsGitHub ModelsManage and compare promptsMCP RegistryNewIntegrate external toolsDEVELOPER WORKFLOWSActionsAutomate any workflowCodespacesInstant dev environmentsIssuesPlan and track workCode ReviewManage code changesAPPLICATION SECURITYGitHub Advanced SecurityFind and fix vulnerabilitiesCode securitySecure your code as you buildSecret protectionStop leaks before they startEXPLOREWhy GitHubDocumentationBlogChangelogMarketplaceView all featuresSolutionsBY COMPANY SIZEEnterprisesSmall and medium teamsStartupsNonprofitsBY USE CASEApp ModernizationDevSecOpsDevOpsCI/CDView all use casesBY INDUSTRYHealthcareFinancial servicesManufacturingGovernmentView all industriesView all solutionsResourcesEXPLORE BY TOPICAISoftware DevelopmentDevOpsSecurityView all topicsEXPLORE BY TYPECustomer storiesEvents & webinarsEbooks & reportsBusiness insightsGitHub SkillsSUPPORT & SERVICESDocumentationCustomer supportCommunity forumTrust centerPartnersOpen SourceCOMMUNITYGitHub SponsorsFund open source developersPROGRAMSSecurity LabMaintainer CommunityAcceleratorArchive ProgramREPOSITORIESTopicsTrendingCollectionsEnterpriseENTERPRISE SOLUTIONSEnterprise platformAI-powered developer platformAVAILABLE ADD-ONSGitHub Advanced SecurityEnterprise-grade security featuresCopilot for BusinessEnterprise-grade AI featuresPremium SupportEnterprise-grade 24/7 supportPricing

Search or jump to...

Search code, repositories, users, issues, pull requests...

Search

Clear

Search syntax tips

Provide feedback


We read every piece of feedback, and take your input very seriously.

Include my email address so I can be contacted

Cancel

Submit feedback

Saved searches

Use saved searches to filter your results more quickly

Name

Query

To see all available qualifiers, see our documentation.

Cancel

Create saved search

Sign in

Sign up

Appearance settings

Resetting focus

You signed in with another tab or window. Reload to refresh your session.
You signed out in another tab or window. Reload to refresh your session.
You switched accounts on another tab or window. Reload to refresh your session.

Dismiss alert

jordanhubbard

/

nanolang

Public template

Notifications
You must be signed in to change notification settings

Fork
11

Star
194

A tiny experimental language designed to be targeted by coding LLMs

License

Apache-2.0 license

194
stars

11
forks

Branches

Tags

Activity

Star

Notifications
You must be signed in to change notification settings

Code

Issues
2

Pull requests
1

Discussions

Actions

Projects
0

Security

Uh oh!

There was an error while loading. Please reload this page.


Insights

Additional navigation options

Code

Issues

Pull requests

Discussions

Actions

Projects

Security

Insights

jordanhubbard/nanolang

 mainBranchesTagsGo to fileCodeOpen more actions menuFolders and filesNameNameLast commit messageLast commit dateLatest commit History1,290 Commits.beads.beads  .cursor.cursor  .factory.factory  .github.github  .vscode.vscode  C-samplesC-samples  docsdocs  editorseditors  examplesexamples  modulesmodules  planningplanning  schemaschema  scriptsscripts  srcsrc  src_nanosrc_nano  stdstd  stdlibstdlib  teststests  toolstools  userguideuserguide  .cursorrules.cursorrules  .gitattributes.gitattributes  .gitignore.gitignore  AGENTS.mdAGENTS.md  CONTRIBUTING.mdCONTRIBUTING.md  CONTRIBUTORS.mdCONTRIBUTORS.md  LICENSELICENSE  MEMORY.mdMEMORY.md  MakefileMakefile  Makefile.gnuMakefile.gnu  README.mdREADME.md  SPEC_AUDIT.mdSPEC_AUDIT.md  packages.jsonpackages.json  spec.jsonspec.json  View all filesRepository files navigationREADMEContributingApache-2.0 licensenanolang

A minimal, LLM-friendly programming language with mandatory testing and unambiguous syntax.
NanoLang transpiles to C for native performance while providing a clean, modern syntax optimized for both human readability and AI code generation.

Self-hosting: NanoLang supports true self-hosting via a Stage 0 → Stage 1 → Stage 2 bootstrap (make bootstrap); see planning/SELF_HOSTING.md.

Quick Start
Install
git clone https://github.com/jordanhubbard/nanolang.git
cd nanolang
make build
This builds the compiler:

bin/nanoc - NanoLang compiler (transpiles to C)

Hello World
Create hello.nano:
fn greet(name: string) -> string {
return (+ "Hello, " name)
}

shadow greet {
assert (str_equals (greet "World") "Hello, World")
}

fn main() -> int {
(println (greet "World"))
return 0
}

shadow main {
assert true
}

Run it:
# Compile to native binary
./bin/nanoc hello.nano -o hello
./hello
Platform Support
Tier 1: Fully Supported ✅
NanoLang is actively tested and supported on:

Ubuntu 22.04+ (x86_64)
Ubuntu 24.04 (ARM64) - Raspberry Pi, AWS Graviton, etc.
macOS 14+ (ARM64/Apple Silicon)
FreeBSD

Tier 2: Windows via WSL 🪟
Windows 10/11 users: NanoLang runs perfectly on Windows via WSL2 (Windows Subsystem for Linux).
Install WSL2:
# In PowerShell (as Administrator)
wsl --install -d Ubuntu
After installation, restart your computer, then:
# Inside WSL Ubuntu terminal
git clone https://github.com/jordanhubbard/nanolang.git
cd nanolang
make
./bin/nanoc examples/language/nl_hello.nano -o hello
./hello
Why WSL? NanoLang's dependencies (SDL2, ncurses, pkg-config) are Unix/POSIX libraries. WSL2 provides a full Linux environment with near-native performance on Windows.
Note: Native Windows binaries (.exe) are not currently supported, but may be added in a future release via cross-compilation.
Tier 3: Experimental 🧪
These platforms should work but are not actively tested in CI:

macOS Intel (via Rosetta 2 on Apple Silicon, or native on older Macs)
Other Linux distributions (Arch, Fedora, Debian, etc.)
OpenBSD (requires manual dependency installation)

Key Features

Prefix Notation - No operator precedence: (+ a (* b c)) is always clear
Mandatory Testing - Every function requires a shadow test block
Static Typing - Catch errors at compile time
Generic Types - Generic unions like Result<T, E> for error handling
Compiled Language - Transpiles to C for native performance
Immutable by Default - Use let mut for mutability
C Interop - Easy FFI via modules with automatic package management
Module System - Automatic dependency installation via module.json
Standard Library - Growing stdlib with Result<T,E>, string ops, math, and more

Documentation
Learning Path

User Guide (HTML) - Progressive tutorial + executable snippets
Getting Started - 15-minute tutorial
Quick Reference - Syntax cheat sheet
Language Specification - Complete reference
Examples - Working examples (all runnable)

Key Topics

Standard Library - Built-in functions
Module System - Creating and using modules
FFI Guide - Calling C functions
Shadow Tests - Testing philosophy
All Documentation - Complete index

Language Overview
Syntax Basics
# Variables (immutable by default)
let x: int = 42
let mut counter: int = 0

# Functions with mandatory tests
fn add(a: int, b: int) -> int {
return (+ a b)
}

shadow add {
assert (== (add 2 3) 5)
assert (== (add -1 1) 0)
}

# Control flow
if (> x 0) {
(println "positive")
} else {
(println "negative or zero")
}

# Loops
let mut i: int = 0
while (< i 10) {
print i
set i (+ i 1)
}

Why Prefix Notation?
No operator precedence to remember:
# Crystal clear - no ambiguity
(+ a (* b c)) # a + (b * c)
(and (> x 0) (< x 10)) # x > 0 && x < 10
(/ (+ a b) (- c d)) # (a + b) / (c - d)

Type System
# Primitives
int, float, bool, string, void

# Composite types
struct Point { x: int, y: int }
enum Status { Pending = 0, Active = 1, Complete = 2 }

# Generic lists
let numbers: List<int> = (List_int_new)
(List_int_push numbers 42)

# First-class functions
fn double(x: int) -> int { return (* x 2) }
let f: fn(int) -> int = double

# Generic unions (NEW!)
union Result<T, E> {
Ok { value: T },
Err { error: E }
}

let success: Result<int, string> = Result.Ok { value: 42 }
let failure: Result<int, string> = Result.Err { error: "oops" }

Standard Library
NanoLang includes a growing standard library:
union Result<T, E> {
Ok { value: T },
Err { error: E }
}

fn divide(a: int, b: int) -> Result<int, string> {
if (== b 0) {
return Result.Err { error: "Division by zero" }
}
return Result.Ok { value: (/ a b) }
}

fn main() -> int {
let result: Result<int, string> = (divide 10 2)

/* Note: Result helper functions (is_ok/unwrap/etc) are planned once
* generic functions are supported. For now, use match.
*/
match result {
Ok(v) => (println v.value),
Err(e) => (println e.error)
}

return 0
}

Examples
Core Examples

hello.nano - Basic structure
calculator.nano - Arithmetic operations
factorial.nano - Recursion
fibonacci.nano - Multiple algorithms
primes.nano - Prime number sieve

Game Examples

snake_ncurses.nano - Classic snake with NCurses UI
game_of_life_ncurses.nano - Conway's Game of Life
asteroids_complete.nano - Full Asteroids game (SDL)
checkers.nano - Checkers with AI (SDL)
boids_sdl.nano - Flocking simulation (SDL)

See examples/README.md for the complete list.
Modules
NanoLang includes several modules with automatic dependency management:
Graphics & Games

ncurses - Terminal UI (interactive games, text interfaces)
sdl - 2D graphics, windows, input (brew install sdl2)
sdl_mixer - Audio playback (brew install sdl2_mixer)
sdl_ttf - Font rendering (brew install sdl2_ttf)
glfw - OpenGL window management (brew install glfw)

Modules automatically install dependencies via package managers (Homebrew, apt, etc.) when first used. See docs/MODULE_SYSTEM.md for details.
Building & Testing
# Build (3-stage component bootstrap)
make build

# Run full test suite
make test

# Quick test (language tests only)
make test-quick

# Build all examples
make examples

# Launch the examples browser
make examples-launcher

# Validate user guide snippets (extract → compile → run)
make userguide-check

# Build static HTML for the user guide
make userguide-html
# Options:
# CMD_TIMEOUT=600 # per-command timeout (seconds)
# USERGUIDE_TIMEOUT=600 # build timeout (seconds)
# USERGUIDE_BUILD_API_DOCS=1 # regenerate API reference
# NANO_USERGUIDE_HIGHLIGHT=0 # disable highlighting (CI default)

# Serve the user guide locally (dev)
make -C userguide serve

# Clean build
make clean

# Install to /usr/local/bin (override with PREFIX=...)
sudo make install
On BSD systems (FreeBSD/OpenBSD/NetBSD), use GNU make: gmake build, gmake test, etc.
Teaching LLMs NanoLang
NanoLang is designed to be LLM-friendly with unambiguous syntax and mandatory testing. To teach an AI system to code in NanoLang:
For LLM Training

MEMORY.md - Complete LLM training reference with patterns, idioms, debugging workflows, and common errors
spec.json - Formal language specification (types, stdlib, syntax, operations)
Examples - Runnable examples demonstrating all features

Quick LLM Bootstrap

Read MEMORY.md first - covers syntax, patterns, testing, debugging
Reference spec.json for stdlib functions and type details
Study examples for idiomatic usage patterns

The combination of MEMORY.md (practical guidance) + spec.json (formal reference) provides complete coverage for code generation and understanding.
Contributing
We welcome contributions! Areas where you can help:

Add examples and tutorials
Improve documentation
Report bugs or suggest features
Create new modules
Implement standard library functions

See CONTRIBUTING.md for guidelines.
Project Status
Current: Production-ready compiler with full self-hosting support.
Completed Features

✅ Complete language implementation (lexer, parser, typechecker, transpiler)
✅ Compiled language (transpiles to C for native performance)
✅ Static typing with inference
✅ Structs, enums, unions, generics
✅ Module system with auto-dependency management
✅ 49+ standard library functions
✅ 90+ working examples
✅ Shadow-test framework
✅ FFI support for C libraries
✅ Memory safety features

See docs/ROADMAP.md for future plans.
Why NanoLang?
NanoLang solves three problems:

LLM Code Generation - Unambiguous syntax reduces AI errors
Testing Discipline - Mandatory tests improve code quality
Simple & Fast - Minimal syntax, native performance

Design Philosophy:

Minimal syntax (18 keywords vs 32 in C)
One obvious way to do things
Tests are part of the language, not an afterthought
Transpile to C for maximum compatibility

License
Apache License 2.0 - See LICENSE file for details.
Links

Documentation: docs/
Examples: examples/
Issues: GitHub Issues
Contributing: CONTRIBUTING.md

About

A tiny experimental language designed to be targeted by coding LLMs

Topics

domain-lang

new-language-design

domain-ai

llm

thought-exercise

vibe-coding

Resources

Readme

License

Apache-2.0 license

Contributing

Contributing

Uh oh!

There was an error while loading. Please reload this page.


Activity
Stars

194
stars
Watchers

4
watching
Forks

11
forks

Report repository

Releases
8

v2.0.8

Latest

Jan 20, 2026


+ 7 releases

Packages
0

No packages published

Contributors
4

jordanhubbard
Jordan Hubbard

factory-droid[bot]

claude
Claude

Copilot

Languages

C
90.0%

Shell
4.4%

Python
2.2%

Gnuplot
1.6%

C++
1.3%

CSS
0.2%

Other
0.3%

Footer

© 2026 GitHub, Inc.

Footer navigation

Terms

Privacy

Security

Status

Community

Docs

Contact

Manage cookies

Do not share my personal information

You can’t perform that action at this time.

NanoLang is a minimalist, experimental programming language designed to serve as an optimal target for coding large language models (LLMs). Created by Jordan Hubbard, the project emphasizes unambiguous syntax, mandatory testing, and performance through transpilation to C. Its design prioritizes simplicity, readability, and compatibility with AI-driven code generation while maintaining native execution efficiency. The language’s structure reflects a deliberate balance between human-friendly conventions and the precision required for reliable LLM interactions. NanoLang’s core philosophy revolves around reducing ambiguity in syntax, enforcing rigorous testing practices, and leveraging existing ecosystems for portability and extensibility.

The language’s syntax is built around prefix notation, eliminating the need for operator precedence rules that often confuse both humans and AI systems. For example, expressions like `(+ a (* b c))` explicitly define operations without relying on implicit order-of-operations logic. This approach ensures clarity, which is critical for LLMs generating code that must be both correct and predictable. Additionally, NanoLang enforces mandatory testing through "shadow tests," requiring every function to be accompanied by a corresponding test block. These tests are integrated directly into the language, ensuring that code quality is maintained throughout development. The shadow test framework allows developers to assert expected outcomes using a simple syntax, such as `(assert (== (add 2 3) 5))`, which verifies the correctness of functions like `add` in the provided Hello World example.

Static typing with type inference is another cornerstone of NanoLang’s design. The language supports primitive types like `int`, `float`, `bool`, and `string`, as well as composite types such as structs, enums, and generic unions. For instance, the `Result<T, E>` union pattern enables robust error handling by distinguishing between success (`Ok`) and failure (`Err`) states. This type system is designed to catch errors at compile time, reducing runtime issues and improving reliability. The use of generics further enhances flexibility, allowing developers to create reusable code structures like `List<int>` for type-safe collections. Immutable variables are the default, with mutability explicitly declared using `let mut`, promoting safer and more predictable code.

NanoLang’s transpilation to C ensures native performance while maintaining compatibility with existing toolchains. By converting high-level constructs into C code, the language leverages the efficiency of compiled languages without sacrificing ease of use. This approach also facilitates integration with C libraries through a module system that supports automatic dependency management. Modules like `ncurses` and `sdl` provide access to terminal UI, graphics, and audio functionalities, with dependencies automatically installed via package managers like Homebrew or apt. The module system is designed to streamline development, allowing developers to focus on application logic rather than infrastructure setup.

The project includes a growing standard library with utilities for string manipulation, mathematical operations, and error handling. For example, the `divide` function demonstrates the use of `Result<T, E>` to handle division by zero gracefully, returning an error message instead of causing a crash. While the standard library is still evolving, its design emphasizes modularity and extensibility, enabling developers to build complex applications with minimal boilerplate. The language also supports first-class functions, allowing for functional programming patterns such as higher-order functions and closures.

NanoLang’s documentation is comprehensive, featuring a user guide with executable code snippets, a language specification, and tutorials for common tasks. The user guide serves as both a learning resource and a reference, with examples that demonstrate syntax, control flow, and advanced features like recursion and pattern matching. The project also provides a suite of examples, ranging from basic arithmetic operations to full-featured games like Snake and Conway’s Game of Life. These examples are designed to be runnable, helping developers understand how to apply NanoLang’s features in real-world scenarios.

Platform support is divided into three tiers: Tier 1 includes Ubuntu, macOS, and FreeBSD with full testing and support; Tier 2 covers Windows via WSL2, which provides a Linux environment for running NanoLang without native Windows binaries; and Tier 3 includes experimental platforms like macOS Intel and other Linux distributions, which may require manual configuration. This tiered approach ensures that the language is accessible across a wide range of systems while maintaining stability on supported platforms.

The project’s development process emphasizes self-hosting, with a three-stage bootstrap process (`Stage 0 → Stage 1 → Stage 2`) that allows the compiler to be written in NanoLang itself. This self-hosting capability is documented in `planning/SELF_HOSTING.md`, highlighting the language’s maturity and its potential for use in compiler development. The build system, managed through Makefiles, supports tasks like compiling the language, running tests, and generating documentation. Developers can also extend the toolchain by contributing new modules or improving existing ones, with clear guidelines provided in `CONTRIBUTING.md`.

NanoLang’s design reflects a focus on teaching LLMs to generate correct and idiomatic code. The `MEMORY.md` file serves as a training reference, outlining patterns, debugging workflows, and common pitfalls for AI systems. The `spec.json` file provides a formal specification of the language’s syntax, types, and standard library functions, ensuring consistency for both human developers and AI models. By combining practical guidance with formal definitions, NanoLang aims to bridge the gap between human-centric programming and machine-generated code.

The project’s current status is described as production-ready, with a fully implemented compiler that supports all core features. Completed milestones include a complete language implementation (lexer, parser, typechecker, transpiler), static typing with inference, and a robust module system. The language also includes 49+ standard library functions and 90+ working examples, demonstrating its versatility for both simple scripts and complex applications. Future plans, outlined in `docs/ROADMAP.md`, suggest further enhancements to the standard library, improved tooling, and expanded platform support.

NanoLang addresses three primary challenges: reducing errors in AI-generated code through unambiguous syntax, enforcing testing discipline to improve reliability, and delivering performance comparable to compiled languages. Its minimal syntax—18 keywords compared to 32 in C—simplifies learning while maintaining expressiveness. The language’s design philosophy emphasizes simplicity, consistency, and integration with existing ecosystems, making it a compelling choice for developers seeking to leverage LLMs in their workflows. By combining these elements, NanoLang represents a novel approach to programming language design that prioritizes both human and machine readability.