A self-replicating software nanobot — a minimal Forth interpreter that is also a networked mesh agent.
Try the live demo | Install: cargo install unit
$ unit
unit v0.26.2 -- seed online
Mesh node a1b2c3d4e5f67890 gen=0 peers=0 fitness=0
> 2 3 + .
5 ok
> : SQUARE DUP * ;
ok
> 7 SQUARE .
49 ok
> SPAWN
spawned child pid=12345 id=cafe0123deadbeef
> SEXP" (* 6 7)" .
42 ok
What's the smallest piece of software that can reproduce and improve itself?
A Forth interpreter. The dictionary IS the genome. The words the unit
runs are the words it evolves. There's no separation between genotype
and phenotype — the code is the organism. You can inspect it (SEE),
mutate it (SMART-MUTATE), share it (SHARE-ALL), and spawn a child
that inherits all of it (SPAWN).
Everything else grew from there.
| Concern | Mechanism |
|---|---|
| Execute | Forth VM — stacks, dictionary, inner interpreter |
| Communicate | S-expression mesh protocol over UDP gossip |
| Replicate | Reads own binary, packages state, spawns child processes |
| Mutate | Genetic programming — 50 candidates, tournament selection, 5 mutation operators |
| Persist | JSON snapshots — hibernate, resurrect, automatic restoration on startup |
These five concerns are the kernel. Everything below emerged from them.
The Forth VM gives the unit a brain: stacks, a dictionary, and an inner interpreter that can define new words at runtime. UDP gossip gives it a voice — units discover each other, share words, and broadcast S-expressions that any language can parse. Self-replication reads the unit's own binary, serializes its state into a UREP package, and spawns a child process that boots with the parent's entire dictionary. The mutation engine applies token-level operations (swap, insert, delete, replace, double) to dictionary entries, with benchmarking to keep beneficial changes and revert harmful ones. JSON persistence lets a unit hibernate and resurrect exactly where it left off.
This is what fits in a 1.2 MB binary with zero dependencies.
The immune system came first. When a unit can't solve a problem, it registers the failure as a fitness challenge and broadcasts it to the mesh. Every unit evolves solutions in parallel. The first solution that passes verification is installed as a dictionary word (SOL-*) that children inherit. Solved challenges generate harder ones — fib(10) leads to fib(15) leads to fib(20), with parsimony pressure rewarding shorter programs.
Metabolic energy makes it real. Every operation costs something: spawning costs 200, each GP generation costs 5, even mesh messages cost 1. Units that run out are throttled. Children inherit a fraction of the parent's energy. Reproduction is a metabolic investment.
Then three orders of evolution emerged. The GP engine evolves solutions
(first-order). A MetaEvolver maintains a population of Forth programs
that generate new challenges from solved ones (second-order). A
ScoringPopulation evolves the functions that judge whether generated
challenges are good (third-order). Use META-DEPTH to see all three
levels operating simultaneously.
Sexual reproduction followed. MATE selects a partner through
tournament selection, and both parents contribute dictionary words to the
child — shared words from the fitter parent, unique words with 50%
probability, antibodies always preserved. Niche construction lets units
that excel at certain challenge types see more of those challenges,
creating ecological specialization across the colony.
None of this was planned from the start. It emerged from asking "what should a self-improving organism do next?"
Three species coexist on one mesh: Rust/Forth units with token-sequence genomes, Go organisms with expression trees, and Python organisms with AST-based symbolic regression. They speak the same S-expression protocol, receive the same challenges, and broadcast solutions using their own GP strategies. Different cognitive substrates, same evolutionary pressures.
Distributed computation fans sub-goals across the mesh as S-expressions. If a peer doesn't respond, the unit falls back to local computation. Swarm mode enables auto-discovery, word sharing, and autonomous spawn/cull with a single command.
> 2 3 + . \ basic arithmetic
5 ok
> : SQUARE DUP * ; \ define a word
ok
> SPAWN \ replicate
spawned child pid=12345 id=cafe0123deadbeef
> SEXP" (* 6 7)" . \ S-expression eval
42 ok
> GP-EVOLVE \ evolve a solution
[gen 0] WINNER: "0 1 10 0 DO OVER + SWAP LOOP DROP ." (fitness=890)
> CHALLENGES \ see the immune system
--- 4 challenges ---
#1 fib10 [SOLVED] reward=100
> ENERGY \ check metabolism
energy: 1097/5000 (earned: 102, spent: 5, efficiency: 20.40)
> MATE \ sexual reproduction
mating with #cafe (fitness=45)...
> NICHE \ ecological profile
--- niche profile ---
fibonacci: 100% (modifier: 2.0x)
See docs/words.md for the complete word reference (309 words).
src/
├── vm/ # Forth virtual machine (~200 primitives)
├── mesh.rs # UDP gossip, peer discovery, cross-machine
├── sexp.rs # S-expression parser and serializer
├── evolve.rs # Genetic programming engine
├── challenges.rs # Challenge registry (immune system)
├── energy.rs # Metabolic energy system
├── landscape.rs # Dynamic fitness landscape, meta-evolution
├── reproduction.rs # Sexual reproduction, dictionary crossover
├── niche.rs # Niche construction, ecological specialization
├── spawn.rs # Self-replication, UREP package format
├── snapshot.rs # JSON persistence and resurrection
├── prelude.fs # Forth prelude (~600 lines)
└── main.rs # REPL, CLI, feature wiring
polyglot/go/ # Go organism (expression trees)
polyglot/python/ # Python organism (AST symbolic regression)
The kernel is ~2,000 lines. The organism is ~36,000. Both are intentional.
223+ Rust tests, 22 Python tests, Go tests. Zero dependencies.
- docs/words.md — complete word reference (309 words)
- docs/protocol.md — S-expression wire format and mesh protocol
- docs/operations.md — monitoring, goals, trust, persistence, swarm mode
| Target | Size |
|---|---|
| Native (macOS arm64, release) | ~1.2 MB |
| WASM (browser) | ~338 KB |
MIT — see LICENSE.
