Synsemadocsv0.6.xENES

Getting Started

Quickstart

Synsema is a programming language designed for AI agents — LLM reasoning, multi-agent coordination, human approval gates, an HTTP server and a deny-by-default security model are built into the language, not bolted on as frameworks. It ships as a single self-contained binary (written in Rust) — no Python, no Node, no runtime to install.

Install§

macOS / Linux:

curl -fsSL https://synsema.com/install.sh | sh

Windows (PowerShell):

irm https://synsema.com/install.ps1 | iex

From npm (Linux, macOS, Windows — the same native binary, nothing else runs; v0.6.3+):

npm i -g synsema          # then: synsema run app.syn
npx synsema run app.syn   # per project, no global install

Updating: synsema update (or npm i -g synsema@latest when npm installed it — the binary notices and says so).

Check it:

synsema version

Hello, world§

The fastest start is the scaffold — it generates a commented hello.syn (a short tour of the language, with its test), a .env.example with every knob explained, a .gitignore, and a .mcp.json that registers the local synsema-code MCP server for your coding agent:

synsema init my-project

Or write it yourself — put this in hello.syn:

hello-world.syn
-- Doc example: your first Synsema program. Comments in English (universal code).
intent: "doc example: hello world + a tiny task"

task greet(name)
    give "Hello, " + name + "!"

print(greet("World"))                 -- run shows: Hello, World!

test "greet builds a friendly message"
    assert_eq(greet("World"), "Hello, World!")
    assert_eq(greet("Synsema"), "Hello, Synsema!")

Run it:

synsema run hello.syn

synsema run executes a file (each print shows up as it happens); synsema test runs the test blocks — of one file, or of several files and directories at once (synsema test a.syn tests/); synsema check parses without running and warns about what changed between versions (a deprecated builtin name, a \u escape, a write that value semantics would lose). Coming from another language, read Counter your priors before you write much.

Your first HTTP server§

Synsema has a production HTTP server built in — no framework to add. Everything is deny-by-default, so you declare what the program may do with require.

require serve(8080)

serve on 8080
    route "GET /hello"
        give {"msg": "hi"}
synsema serve app.syn          # → http://127.0.0.1:8080/hello

Your first web page§

The same server serves real HTML. A page is a template with { holes }; your CSS/JS live in static/ (they hot-reload per request — edit, refresh, done):

require serve(8080)
require file.read("./static/**")         -- static serves this folder: that is reading it
require file.read("pages/*")             -- render() reads the template from disk

serve on 8080
    static "/assets" from "./static"        -- app.css, app.js
    route "GET /"
        give render("pages/home.html", {"title": "My site"})
<!-- pages/home.html -->
<!DOCTYPE html><html><head><title>{ title }</title>
<link rel="stylesheet" href="/assets/app.css"></head>
<body><h1>{ title }</h1></body></html>

Both require file.read lines are needed: serving a folder and rendering a template are reading files, and nothing reads a file without saying so. Leave out the first and the server does not start — the error names the line to add (add require file.read("static/")); leave out the second and the page is a 500 Capability not granted: file_read("pages/home.html"). is "this folder and everything below it".

Full walkthrough (layout, components, forms, error pages): Build a website.

Your first LLM call§

The LLM is a built-in primitive. Put your provider key in .env (it is never exposed to the program), then:

require llm

let summary be generate "a one-line summary" given report
let action be decide between ["approve", "reject"] given request

The result of a decide is validated to be one of the options — with automatic retries. See LLM in the sidebar for native ops and for calling a provider's HTTP API directly.

Next§