Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Cheatsheet

The language and the command line of Semaprax 0.9.0 on one page. Each row links to the page that explains it.

The daily loop

Run these in your project directory.

semaprax fmt .            # rewrite source to the one canonical form (--check only reports)
semaprax check .          # parse, resolve, type-check, verify
semaprax test .           # run the project's test functions
semaprax run .            # run main and print its i64 result
semaprax build . --target web -o dist/web

fmt writes files; fmt --check does not. check never runs your code; run and test do. For one file, semaprax fmt f.spx && semaprax run f.spx is the whole loop. Add --json to check, run or test for one JSON object per diagnostic.

Commands by task

Run semaprax help all for the full list, or see the Command catalog.

I want toCommandPage
Start a projectsemaprax new demo (--template library|service)First project
Read a declaration’s meaningdoc <file>, query <project> --id <id>, context <input> <id> --depth 1 --max-bytes 4096, graph <file>Explore
Find who calls whatquery <project> --calls <id>, --called-by <id>Explore
Look at a project visuallyexplore <manifest> --format html --output out.htmlExplore
Change code by meaningchange preview, patch, impact, reviewShipping
Pin and compare an interfacelock . --write|--verify|--compare base.lockShipping
Build for a targetbuild . --target native|web|wasm|npm|ociTargets
Check my toolchain or a downloaddoctor, version, release verify <dir>Targets, Shipping
Reload code while editingdev semaprax.toml --jsonlTargets
Serve a project to an agentservice <project> [--mcp]Shipping
Run an agent in a coding harnessharness setup, harness run, harness bridgeHarness
Run an agent or check its definitionagent inspect|run|replayAgent programs
Get an error’s fixhelp diagnostic SPX-T208Diagnostics
Look up a library functionhelp library compareStandard library
See a language topichelp language topics, help language ownershipEssentials
Copy a declaration shapehelp shapes recordTypes

The language at a glance

NeedSpellingPage
A filemodule app.name; first, then declarationsEssentials
Stable identity@id("app.name.fn") before every declarationEssentials
Entry pointexactly fn main() -> i64Essentials
Result of a blockA tail expression, with no return and no trailing ;Essentials
Bindingslet x = 1; immutable; let mut n = 0; then n = n + 1;Essentials
Number typesi64 (default), i32, u8, usize, f64, f32; suffix 5i32, 3usize; operators never mix typesTypes
Other scalarsbool, char ('a'), string (owned UTF-8), str (borrowed view)Ownership
Conditionalif c { a } else { b }; always an expression, no else ifEssentials
Loop on a conditionwhile cond { ...; cond }; the last line is the continuation testLoops
Loop over a vectorfor item in values { ...; 0 } over an immutable Vec bindingLoops
Consume an iteratorfor own item in it { ... }; match own on IterStepLoops
Recordrecord P { @id("p.x") x: i64, }; build P { x: 1 }; update p with { x: 2 }Types
Variantcases Name, or Name { f: i64, }; build Shape::Dot {}Types
Matchmatch v { Shape::Box { width: w } => w, _ => 0, }; guards n if n < 0; or-patterns -1 | -2Matching
Option and ResultOption<i64>::Some { value: 1 }; match Option::Some { value: v }; ? in a Result functionMatching
Classclass Dog : Animal { fn m(self: Dog) -> i64 { ... } }; call d.m(); super.m()Classes
Genericsfn id<T>(v: T) -> T; call id<i64>(4)Functions
Function valuesfn(x: i64) -> i64 { x + 1 }; parameter f: fn(i64) -> i64Functions
Contractsrequires x >= 0 and ensures result >= 0 between signature and bodyContracts
Effectspermit { process.stdout.write } on the module, uses { ... } on each functionContracts
Ownershipown T consumes; borrow T reads; a moved value cannot be reusedOwnership
Resourcesresource R { drop trivial; } or drop import "host.symbol";Resources
Stringsstring_concat(a, b); view string_as_str(binding); bytes str_as_bytes(view)Built-ins
Vectorsvec_with_capacity<i64>(4usize); v = vec_push<i64>(v, 1);Collections
Laws@id("l.order") law relational (a: i64, b: i64) a <= b || b < a evidence smt_proved;Laws
Session protocolsession protocol "name" { states {...} initial S; on S label: send T via "id" -> S2; }semaprax help language
Import across filesuse function @id("pkg.fn") from other.module as name; right after moduleModules
A testfn test_add() -> i64 with an @id in a test module; return 0 to passTesting
Standard library[dependencies] std.core = "^0.1.0" then use function @id("std.core.min") ...Standard library

Habits that fail: return, else if, x += 1, tuples, a[0], "a" + "b", Some(1), i++, break, as casts, macros. The fix for each is in Diagnostics.

A complete syntax reminder

module app.reminder;

@id("reminder.double")
fn double(value: i64) -> i64
    requires value >= 0
    ensures result == value * 2
{
    value * 2
}

@id("app.main")
fn main() -> i64
{
    let answer = double(21);
    if answer == 42 { answer } else { 0 }
}

Reading a command synopsis

Angle brackets name values to replace, square brackets are optional parts, and | means choose one. Do not paste the brackets into a shell. If a command says <input>, give it a .spx file, a project directory or semaprax.toml.

Need a word explained? Open the glossary.