a programming language without fluff
git clone https://git.smesh.lol/moxie.git

a programming language without fluff
"Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away." - Antoine de Saint-Exupery
Saint-Exupery was an aircraft engineer. Software is like aircraft - what fails in the air is usually needless complexity.
A compiled systems language for domain-isolated event-driven programs. Each program is a tree of domains - isolated OS processes communicating through serialized IPC channels. No goroutines, no shared memory, no data races.
Moxie descends from TinyGo. All embedded targets and threading infrastructure have been stripped. What remains is a compilation pipeline for Linux, Darwin, and browser JS, rewired for single-threaded domains with process-level isolation via spawn.
clang-22, ld.lld-22, llvm-link-22)pacman -S llvm clang lld `sh
sudo ln -sf /bin/clang /usr/local/bin/clang-22
sudo ln -sf /bin/ld.lld /usr/local/bin/ld.lld-22
sudo ln -sf /bin/llvm-link /usr/local/bin/llvm-link-22
`
# Build the compiler
./build.sh
# Build a program
export MOXIEROOT=/path/to/moxie
moxie build -o hello .
./hello
package main
import "moxie"
func worker(n moxie.Int32) {
println("child domain:", n)
}
func main() {
spawn(worker, moxie.Int32(42))
println("parent continues")
}
Each domain runs a single thread. No goroutines, no scheduler, no task switching.
| Construct | Behavior |
|---|---|
| Unbuffered channel send | Execution jumps to the waiting select case |
| Buffered channel send | Message queued for the next select iteration |
select | Event handler - blocks until a channel, I/O event, or timer fires |
spawn | Creates a child domain (OS process) with IPC channels |
Within a domain, channels and select are the event dispatch system. Between domains, spawn and IPC channels provide concurrent execution with complete memory isolation.
| Traditional | Moxie | Effect |
|---|---|---|
string (immutable) / []byte (mutable) | string = []byte | Same type, mutually assignable. \| for concatenation. |
int (platform-sized) | int32 always | 32-bit on all targets. |
spawn is a language builtin. All data arguments must implement moxie.Codec for serialization. No pointers, functions, or interfaces cross the boundary. Non-constant values are moved (ownership transfer).
import "moxie"
type Codec interface {
EncodeTo(w io.Writer) error
DecodeFrom(r io.Reader) error
}
Built-in codec types: Bool, Int8, Uint8, Int16, Uint16, Int32, Uint32, Int64, Uint64, Float32, Float64, Bytes. Little-endian default. Big-endian aliases (BigInt32, BigUint64, etc.) for network protocols.
| Removed | Use Instead |
|---|---|
go f() | Channels + select, or spawn |
new(T) | &T{} |
+ on text | \| pipe operator |
fallthrough | case A, B: |
complex64/128 | Not supported |
uintptr | Explicit pointer types |
import "strings" | import "bytes" |
Spawn channels are non-blocking on both sides. The runtime uses moxie_peek (non-blocking) to check for data before reading, and pipeSendNB (non-blocking) for sends. When the pipe buffer is full or empty, the runtime yields for 1ms and retries indefinitely until the operation succeeds or the pipe closes. No domain ever blocks in a syscall waiting for the other side.
The spawn socketpair is full-duplex - both sides can send simultaneously. Both sides are symmetric concurrent peers. Backpressure is expressed by pipe buffer fullness, not by sender blocking.
chanID 0 = control (close signals), chanID 1 = first spawn channel arg, chanID 2 = second, etc.
| Operation | Behavior |
|---|---|
ch <- v | Non-blocking send with retry-and-yield (1ms). Retries until success or pipe close. |
v := <-ch | Non-blocking recv with retry-and-yield (1ms). Retries until data arrives or pipe close. |
select { case v := <-ch: } | Non-blocking poll via tryPipeRecv/tryPipeSend. |
close(ch) | Sends close marker (chanID 0) to remote, then closes locally. |
| Target | Output | Memory |
|---|---|---|
| linux/amd64 | Static ELF | Arena allocator |
| linux/arm64 | Static ELF | Arena allocator |
| darwin/amd64 | Mach-O | Arena allocator |
| darwin/arm64 | Mach-O | Arena allocator |
| js/wasm | JavaScript + runtime | Bump allocator |
All native binaries are fully statically linked.
EXAMPLE_CLAUDE.md is a CLAUDE.md template that teaches Claude (or other AI coding assistants) how to write correct Moxie code. Drop it into your project's CLAUDE.md to get accurate code generation that respects Moxie's restrictions and patterns.
The architecture patterns document describes a general CSP/Actor model that applies beyond Moxie. Three libraries implement the intra-domain actor patterns (sections 3.1-3.6) for other languages:
go get git.smesh.lol/actorpickle = { git = "https://git.smesh.lol/pickle" }npm install annealmoxie/
├── _mxc_stage4/ # Self-hosting compiler (Moxie source)
├── compile/ # Compiler library (forward-ported from stage4)
├── build.sh # Bootstrap build script
├── release.sh # Release tarball builder
├── install.sh # Remote install script
├── jsruntime/ # JS host shims for WASM target
├── sysroot/ # Precompiled runtime bitcode, musl, compiler-rt
├── src/ # Target-side sources (compiled INTO programs)
│ ├── runtime/ # Runtime: scheduler, channels, arena, spawn, stringers
│ ├── internal/task/ # Cooperative task system, context switching
│ ├── moxie/ # Codec interface, built-in codec types
│ └── ... # Stdlib (.mx files)
└── docs/ # Language reference, porting guide, architecture