Machine-readable diagnostics, auto-generated capability docs, and on-device LLM inference — in a self-hosting compiled language with native performance. Designed so an AI agent writes, reads and fixes it without guessing.
Most languages were designed for humans and later poked at by tools. Nyx was built the other way around: every error, every capability, every rough edge is something a model can parse, act on, and report back — deterministically.
NYX_DIAG=json emits every diagnostic as NDJSON with a stable code (NYX01xx–NYX12xx), line:column, and a fix hint — in both the parse and semantic phases, multi-error, bilingual. No scraping stderr, no guessing what failed.nyx init seeds AGENTS.md (a playbook) and CAPABILITIES.md (a by-task index of the stdlib), and nyx build keeps them current. An agent learns what exists without reading the source of every module.std/llm binds llama.cpp: load a GGUF model, generate, stream tokens back into Nyx — deterministic drop frees the model exactly once. AI isn't only a service you call out to; it's a library you link.nyx report) turns dead-ends into structured feedback. Every rough edge is a signal, not a silent failure.$ NYX_DIAG=json nyx build {"phase":"semantic","code":"NYX1005","line":12,"col":18, "message":"argument 2 of 'indexOf' must be int, got String", "hint":"pass a byte offset, e.g. s.indexOf(needle, 0)"} # one line, stable code, exact location, actionable hint — for the model, not the human
Clean, familiar syntax. Compiles to native code via LLVM.
fn handle_user(req: Request) -> Response { let id: String = req.params.get("id") return response_json(200, "{\"id\": \"" + id + "\"}") } fn main() { let app: App = app_new() app_use(app, mw_cors) app_get(app, "/users/{id}", handle_user) serve_app(app, 3000, 64) }
$ redis-cli -p 6382 > CREATE TABLE events (id INTEGER PRIMARY KEY, name TEXT) OK > INSERT INTO events VALUES (1, 'deploy') OK > SELECT name FROM events WHERE id = 1 1) "deploy"
$ redis-cli -p 6381 > ENQUEUE jobs '{"task": "send_email", "to": "alice@example.com"}' "msg_0001" > DEQUEUE jobs 1) "msg_0001" 2) "{\"task\": \"send_email\"}" > ACK jobs msg_0001 OK
fn handle_request(method: String, path: String, headers: Array, body: String) -> Array { let hdrs: Array = ["content-type", "application/json", "server", "nyx-http2"] return [200, hdrs, "{\"ok\": true, \"protocol\": \"h2c\"}"] } fn main() -> int { h2_serve(3004, 4, handle_request) return 0 }
Everything that serves this website is written in Nyx.
Compiled to machine code via LLVM. At or above C on compute; the gap is allocation-heavy work (GC). Ratios are the portable metric.
Not a roadmap — these are shipped and running in production. Full changelog →
#[affine] types, and dangling-reference escape analysis — opt-in with NYX_BORROW=error.make wasm runs Nyx in the browser with DOM + events; std/llm binds llama.cpp for on-device inference.NYX_DIAG=json with stable codes, line:column, multi-error in parse and semantic phases. Bilingual via NYX_LANG. The parser never hangs.$ curl -sSf https://nyxlang.com/install.sh | sh
Linux (x86_64, ARM64) · Requires Clang · ~10 seconds
Verify: $ nyx --version → nyx 0.22.0
$ echo 'fn main() { print("Hello!") }' > hello.nx $ nyx run hello.nx Hello!
$ nyx init myapp $ cd myapp && nyx run Hello from myapp!
import "std/http" fn serve_req(request: Array) -> String { return http_response(200, "Hello from Nyx!") } fn main() { http_serve_mt(8080, 4, serve_req) }
$ nyx run server.nx # Open http://localhost:8080
import "std/web" fn get_users(req: Request, resp: Response) { response_json(resp, "[{\"name\": \"Alice\"}]") } fn main() { let app: App = app_new() app_get(app, "/api/users", get_users) serve_app(app, 3000, 16) }
fn main() { let conn: int = tcp_connect("localhost", 6380) tcp_write(conn, "SET name Alice\r\n") let resp: String = tcp_read(conn) print(resp) // +OK tcp_close(conn) }
fn main() { let content: String = read_file("data.csv") let lines: Array = content.split("\n") var count: int = 0 for line in lines { if line.contains("error") { print("Found: " + line) count = count + 1 } } print("Total: " + int_to_string(count)) }
fn work(id: int, ch: Map) -> int { print("Worker " + int_to_string(id)) channel_send(ch, id * 10) return 0 } fn main() { let ch: Map = channel_new(2) thread_spawn(fn() -> int { return work(1, ch) }) thread_spawn(fn() -> int { return work(2, ch) }) let r1: int = channel_recv(ch) let r2: int = channel_recv(ch) print(int_to_string(r1) + ", " + int_to_string(r2)) }
31 chapters · Bilingual EN/ES · From basics to building databases
Everything you need to create, build, run, and share Nyx projects.
$ curl -sSf https://nyxlang.com/install.sh | sh Nyx installed successfully!
Installs to ~/.nyx/ and links nyx to ~/.local/bin/nyx. Adds PATH to your shell profile automatically.
$ nyx update Updating Nyx... Rebuilding compiler... Rebuilding package manager... Nyx updated successfully. nyx 0.22.0
Pulls the latest source and recompiles. Run this anytime to get new features and fixes.
$ nyx uninstall Nyx has been uninstalled. Removed: ~/.nyx/ Removed: ~/.local/bin/nyx
Completely removes Nyx from your system. Clean and reversible.
$ mkdir myapp && cd myapp $ nyx init Initialized project: myapp Created: nyx.toml, src/main.nx Build: nyx build Run: nyx run
nyx init creates two files: nyx.toml (project config) and src/main.nx (entry point).
myapp/
nyx.toml # Project configuration
src/
main.nx # Entry point (fn main)
packages/ # Dependencies (auto-created)
nyx.lock # Lock file (auto-generated)
# Every Nyx project has a nyx.toml at its root [package] name = "myapp" # Project name (used as binary name) version = "0.1.0" # Semantic version main = "src/main.nx" # Entry point file description = "..." # Optional description no_gc = false # Optional: systems mode (no GC) [dependencies] nyx-kv = "*" # From registry (github.com/nyxlang-dev/) mylib = "https://..." # From custom URL
$ nyx build # Compile (debug) Building: myapp v0.1.0 Compiling: src/main.nx ✓ Built: myapp $ nyx build --release # Compile with optimizations (-O2) $ ./myapp # Run the compiled binary
$ nyx run # Build + execute (inside a project) Hello from myapp!
$ nyx run hello.nx # Compile and run a standalone file Hello! $ nyx hello.nx # Shorthand — same result Hello!
No nyx.toml needed. Perfect for scripts and quick experiments.
$ nyx add nyx-kv Adding package: nyx-kv Fetching: https://github.com/nyxlang-dev/nyx-kv Updated nyx.toml Package 'nyx-kv' added.
Packages are fetched from github.com/nyxlang-dev/<name> by default and stored in packages/.
$ nyx add mylib --from https://github.com/user/mylib Package 'mylib' added.
Use --from to fetch from any Git repository.
$ rm -rf packages/ # Delete local packages $ nyx build # They get re-fetched automatically Resolving: nyx-kv Fetched: nyx-kv ✓ Built: myapp
Dependencies listed in nyx.toml are automatically resolved on build. The nyx.lock file records exact versions.
| Command | Description |
|---|---|
nyx init | Create a new project (nyx.toml + src/main.nx) |
nyx build | Compile the project |
nyx build --release | Compile with optimizations |
nyx run | Build and run the project |
nyx run file.nx | Compile and run a single file |
nyx add <pkg> | Add a dependency from the registry |
nyx add <pkg> --from <url> | Add a dependency from a custom URL |
nyx info | Show project details |
nyx update | Update Nyx to the latest version |
nyx uninstall | Remove Nyx from your system |
nyx --version | Show installed version |
31 chapters covering everything from basics to production systems. Bilingual EN/ES.
Apache 2.0 licensed. Contributions welcome.