Getting Started with Synoema

From installation to your first project in 5 minutes

1. Installation

Pre-built binary (recommended)

Download from GitHub Releases for macOS, Linux, or Windows:

./synoema install   # copies to ~/.synoema/bin, adds to PATH

From source (requires Rust)

git clone https://github.com/Delimitter/synoema
cd synoema
cargo install --path lang/crates/synoema-repl

MCP server only (no Rust needed)

npx synoema-mcp

Verify installation

synoema eval "6 * 7"
# 42

2. Your First Program

Create a project

synoema init myapp
cd myapp

This creates:

myapp/
  src/
    main.sno      # entry point
  synoema.toml    # project config

Edit src/main.sno

-- My first Synoema program

greet name = "Hello, ${name}!"

main = print (greet "World")

Run it

synoema run src/main.sno
# Hello, World!

3. Core Concepts

Functions are equations

No def, no return. Just name args = body. The last expression is the result:

double x = x * 2
add x y = x + y
greet name = "Hello, ${name}!"

Pattern matching with multiple equations

Define the same function multiple times with different patterns. First match wins:

fac 0 = 1
fac n = n * fac (n - 1)

describe 0 = "zero"
describe 1 = "one"
describe _ = "many"

Lists use spaces, not commas

nums = [1 2 3 4 5]        -- NOT [1, 2, 3]
empty = []
range = [1..10]            -- [1 2 3 ... 10]
combined = [1 2] ++ [3 4]  -- [1 2 3 4]

Ternary instead of if/else

abs x = ? x < 0 -> -x : x

classify n =
  ? n > 0  -> "positive"
  : ? n < 0  -> "negative"
  : "zero"

Pipes for data flow

result = [1..20]
  |> filter even
  |> map (\x -> x * x)
  |> sum
-- 1140

4. Running Programs

Interpreter (full features)

synoema run program.sno

Supports all features: file I/O, TCP networking, HTTP, channels, subprocess execution.

JIT compiler (fast execution)

synoema jit program.sno

Cranelift JIT compilation — ~3x faster than interpreter, ~3x faster than Python. Does not support I/O or concurrency.

Evaluate expressions

synoema eval "map (\x -> x * x) [1 2 3 4 5]"
# [1 4 9 16 25]

synoema eval "foldl (\a b -> a + b) 0 [1..100]"
# 5050

Watch mode

synoema watch run program.sno

Automatically re-runs on file changes. Great for iterative development.

Build to bytecode

synoema build program.sno    # outputs program.sno.bc
synoema run program.sno.bc   # run from bytecode

5. Working with Data

Records (like structs/objects)

-- Create
user = {name = "Alice", age = 30}

-- Access fields
user.name              -- "Alice"

-- Update (spread syntax)
older = {...user, age = user.age + 1}

-- Pattern match
greet {name, age} = "${name} is ${show age}"

Algebraic data types (like enums)

-- Define
Shape = Circle Float | Rect Float Float | Point

-- Construct
s = Circle 5.0

-- Pattern match
area (Circle r)  = 3.14159 * r * r
area (Rect w h)  = w * h
area Point       = 0.0

Error handling with Result

-- Functions that can fail return Result
safe_div x 0 = Err "division by zero"
safe_div x y = Ok (x / y)

-- Chain with and_then
compute x =
  a <- safe_div x 2
  b <- safe_div a 3
  Ok (a + b)

-- Extract value
main =
  result = safe_div 10 3
  print (unwrap_or 0 result)    -- 3

6. Input / Output

Console

main =
  print "What is your name?"
  name <- readline
  print "Hello, ${name}!"

File I/O

-- Read entire file
content = file_read "data.txt"

-- Line by line
main =
  fd = fd_open "data.txt"
  line1 = fd_readline fd
  line2 = fd_readline fd
  fd_close fd
  print "${line1}, ${line2}"

-- Write
main =
  fd = fd_open_write "output.txt"
  fd_write fd "Hello, file!"
  fd_close fd

HTTP requests

main =
  result = http_get "http://httpbin.org/get"
  ? result
    -> Ok body -> print body
    -> Err msg -> print "Error: ${msg}"

Run external commands

main =
  fd = fd_popen "ls -la"
  line = fd_readline fd
  print line
  fd_close fd

TCP server

handle client =
  req = fd_readline client
  fd_write client "HTTP/1.0 200 OK\r\n\r\nHello!"
  fd_close client

main =
  listener = tcp_listen 8080
  print "Listening on :8080"
  loop l = handle (tcp_accept l) ; loop l
  loop listener

7. Testing

Doctests (in doc comments)

--- Compute factorial.
--- example: fac 5 == 120
--- example: fac 0 == 1
fac 0 = 1
fac n = n * fac (n - 1)

Unit tests

test "base case" = fac 0 == 1
test "fac 5"     = fac 5 == 120
test "fac 10"    = fac 10 == 3628800

Property tests

test "reverse is involution" =
  prop xs -> reverse (reverse xs) == xs

test "sort is sorted" =
  prop xs -> is_sorted (sort xs)

Run tests

synoema test src/main.sno       # single file
synoema test src/                # entire directory

8. Using with LLMs

MCP Server (Claude, Cursor, Zed)

-- Add to your MCP config:
{
  "mcpServers": {
    "synoema": {
      "command": "npx",
      "args": ["synoema-mcp"]
    }
  }
}

-- Available tools:
-- eval: evaluate Synoema expressions
-- typecheck: check types without running
-- run: execute a Synoema program

Constrained decoding (llama.cpp)

./main -m model.gguf \
  --grammar-file synoema.gbnf \
  -p "-- Quicksort in Synoema" \
  -n 128

GBNF grammar guarantees 100% syntactically valid output. No post-processing needed.

Prompt template for code generation

System: You write Synoema code. Key rules:
- Functions: name args = body (no def/return)
- Lists: [1 2 3] (spaces, no commas)
- Ternary: ? cond -> then : else
- Pipes: x |> f |> g
- Lambda: \x -> expr
- Concat: ++ (strings/lists)
- Pattern match via multiple equations

User: Write a function that removes duplicates from a list

9. IDE Support

VS Code extension

cd vscode-extension && ./install.sh

LSP server

Built-in Language Server Protocol support:

cargo install --path lang/crates/synoema-lsp

10. CLI Cheatsheet

CommandWhat it does
synoema run file.snoRun with interpreter (full I/O)
synoema jit file.snoRun with JIT (~3x faster)
synoema eval "expr"Evaluate expression
synoema build file.snoCompile to bytecode
synoema test dir/Run doctests + unit + property tests
synoema doc file.snoGenerate documentation
synoema doc --contracts file.snoContract summary table
synoema watch run file.snoWatch + re-run on change
synoema init myappScaffold new project
synoema installInstall to ~/.synoema/bin
synoema changelog old.sno new.snoAPI diff (type + contract changes)
synoema --errors json run file.snoMachine-readable errors for LLMs

11. Deployment & Daemon Mode

Synoema programs (including HTTP servers) run as regular processes. To run as a background daemon, use OS-level process management.

Quick: nohup (any Unix)

# Start in background, log to file
nohup synoema run server.sno > server.log 2>&1 &
echo $! > server.pid

# Stop
kill $(cat server.pid)

macOS: launchd (auto-restart, boot start)

Create ~/Library/LaunchAgents/com.synoema.website.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>
  <string>com.synoema.website</string>
  <key>ProgramArguments</key>
  <array>
    <string>/Users/YOU/.synoema/bin/synoema</string>
    <string>run</string>
    <string>/path/to/website.sno</string>
  </array>
  <key>EnvironmentVariables</key>
  <dict>
    <key>SNO_PORT</key>
    <string>3000</string>
    <key>SNO_STATIC_DIR</key>
    <string>/path/to/static</string>
    <key>SNO_BASE_DIR</key>
    <string>/path/to/pages</string>
  </dict>
  <key>WorkingDirectory</key>
  <string>/path/to/project</string>
  <key>RunAtLoad</key>
  <true/>
  <key>KeepAlive</key>
  <true/>
  <key>StandardOutPath</key>
  <string>/tmp/synoema-website.log</string>
  <key>StandardErrorPath</key>
  <string>/tmp/synoema-website.err</string>
</dict>
</plist>
# Load (starts immediately + on boot)
launchctl load ~/Library/LaunchAgents/com.synoema.website.plist

# Unload (stop)
launchctl unload ~/Library/LaunchAgents/com.synoema.website.plist

# Check status
launchctl list | grep synoema

Linux: systemd (auto-restart, boot start)

Create /etc/systemd/system/synoema-website.service:

[Unit]
Description=Synoema Website Server
After=network.target

[Service]
Type=simple
User=www-data
WorkingDirectory=/opt/synoema
Environment=SNO_PORT=3000
Environment=SNO_STATIC_DIR=/opt/synoema/static
Environment=SNO_BASE_DIR=/opt/synoema/pages
ExecStart=/usr/local/bin/synoema run /opt/synoema/website.sno
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
# Enable and start
sudo systemctl enable synoema-website
sudo systemctl start synoema-website

# Check status / logs
systemctl status synoema-website
journalctl -u synoema-website -f

Docker

FROM rust:1.75-slim AS build
WORKDIR /app
COPY . .
RUN cargo install --path lang/crates/synoema-repl

FROM debian:bookworm-slim
COPY --from=build /usr/local/cargo/bin/synoema /usr/local/bin/
COPY examples/website/ /app/website/
WORKDIR /app
ENV SNO_PORT=3000
ENV SNO_STATIC_DIR=/app/website/static
ENV SNO_BASE_DIR=/app/website
EXPOSE 3000
CMD ["synoema", "run", "/app/website/website.sno"]
docker build -t synoema-website .
docker run -d -p 3000:3000 --name sno-web synoema-website

Environment variables

VariableDefaultDescription
SNO_PORT3000TCP port
SNO_STATIC_DIRexamples/website/staticStatic files directory
SNO_BASE_DIRexamples/websiteHTML pages directory
SNO_CACHE_TTL3600Static asset cache max-age (seconds)
SNO_VERSION0.1.0-alpha.3Version shown in headers/footer

Next Steps

Read the Docs

Full language reference with types, operators, standard library, and I/O.

Study Examples

38 example programs covering algorithms, data structures, servers, and tools.

Try Online

Experiment in the playground — no installation needed.