Packages Guide
Everything you need to know about the Synoema package ecosystem — from installing your first package to publishing your own.
1. Using packages
The Synoema package manager is built into the CLI. One command installs a package and pins it to your project.
1.1 Finding packages
Browse the packages catalog on this site, or search from the CLI:
sno pkg search http
sno pkg search "time series"
sno pkg search --json iot # machine-readable output
1.2 Installing a package
# Install latest version
sno pkg add sno-http
# Install a specific version
sno pkg add sno-http@0.2.0
# Install from a local path (development)
sno pkg add ./my-local-lib
# Install from a URL
sno pkg add https://example.com/my-pkg.tar.gz
Packages are stored in ~/.sno/packages/<name>@<version>/. No system-wide changes — fully sandboxed.
1.3 Importing a package in your code
Use the import keyword at the top of your .sno file:
import "sno-http"
-- Use exported functions directly
main =
http_serve 3000 (\method path ->
http_html "<h1>Hello</h1>")
Synoema resolves the import to ~/.sno/packages/sno-http@latest/lib.sno automatically. If multiple versions are installed, it picks the highest compatible one.
1.4 Listing installed packages
sno pkg list # human-readable table
sno pkg list --json # machine-readable, includes compat status
1.5 Removing a package
sno pkg remove sno-http
2. Creating a package
A Synoema package is a directory containing at minimum two files: sno.toml (manifest) and lib.sno (library code).
2.1 Directory layout
my-pkg/
sno.toml # manifest — required
lib.sno # library entry point — required
README.md # optional but recommended
examples/ # optional example programs
demo.sno
2.2 sno.toml manifest
The manifest describes your package for the registry and the package manager.
[package]
name = "my-pkg"
version = "0.1.0"
description = "A short description (shown in search results)"
keywords = ["iot", "sensors", "data"]
license = "MIT"
author = "Your Name <you@example.com>"
min_lang_version = "0.1.0-beta.1"
# Which functions/values this package exports
[package.exports]
functions = ["process_data", "format_result", "DEFAULT_TIMEOUT"]
# How LLM agents should use this package
[package.use_cases]
examples = [
"Process raw sensor readings into calibrated values",
"Format telemetry data for MQTT publishing"
]
# Runtime capabilities (used for safety checks in --untrusted mode)
[package.capabilities]
network = false
fs_read = false
fs_write = false
exec = false
2.3 lib.sno — library entry point
Write your library functions in lib.sno. Everything at the top level is exported (subject to [package.exports] filtering in the registry).
-- my-pkg/lib.sno
DEFAULT_TIMEOUT = 5000
-- Process a raw integer reading into a calibrated float
process_data raw calibration_factor =
(to_float raw) * calibration_factor
-- Format a value for display
format_result label value unit =
label ++ ": " ++ show value ++ " " ++ unit
Keep lib.sno pure when possible — avoid side effects at the top level. Side effects (network, file I/O) should be inside functions, not executed on import.
2.4 Type-checking your package
cd my-pkg/
sno check lib.sno # parse + type-check without running
sno fmt lib.sno # auto-format in-place
2.5 Testing locally
Create an example program that imports your package by local path:
-- examples/demo.sno
import "./lib.sno" -- relative path import
main =
result = process_data 1024 0.0488
print (format_result "Temperature" result "°C")
sno run examples/demo.sno
2.6 Using a package from another package
Install the dependency, then import it in lib.sno:
sno pkg add sno-http
-- lib.sno
import "sno-http"
my_server port =
http_serve port (\m p -> http_html "<h1>OK</h1>")
3. Publishing to the registry
3.1 Sign in
Publishing requires a Synoema account (GitHub or Google OAuth):
sno pkg login
This opens your browser for OAuth and saves a session token to ~/.sno/config.toml. For CI/CD environments, use an API key instead:
# Create an API key from your profile page
# https://synoema.tech/profile
sno pkg login --key sno_your_api_key_here
3.2 Prepare your package
Before publishing, verify everything is correct:
cd my-pkg/
# 1. Format code
sno fmt lib.sno
# 2. Type-check
sno check lib.sno
# 3. Verify sno.toml is valid and complete
# (name, version, description, keywords, license are required)
cat sno.toml
3.3 Publish
sno publish
This command (run from the package directory):
- Validates
sno.tomlfor required fields - Runs
sno checkonlib.sno(type-checks source) - Scans for unsafe binary content
- Detects breaking changes vs. the previous published version (type + contract diff)
- Uploads the source archive to the registry
On success, the package is immediately available at synoema.tech/packages.
3.4 Breaking-change detection
The registry compares the type signatures and contracts of all exported functions between versions. If a breaking change is detected (removed function, changed type, stricter contract), you'll see a warning:
⚠ Breaking change detected:
process_data: was (Int -> Float -> Float), now (Int -> Int -> Float -> Float)
(added parameter — callers must be updated)
Bump major version? [y/N]
3.5 Yanking a version
If you publish a broken version, yank it to prevent new installs (existing installs are not affected):
sno publish --yank 0.1.1 # yank specific version
3.6 Re-publishing an existing version
Not allowed. Each version is immutable. Bump the patch version instead:
# Edit sno.toml: version = "0.1.1"
sno publish
4. Versioning & semver
Synoema packages use semantic versioning (semver): MAJOR.MINOR.PATCH[-pre].
| Change type | Bump | Example |
|---|---|---|
| Bug fix, no API change | PATCH |
0.1.0 → 0.1.1 |
| New function, backward-compatible | MINOR |
0.1.1 → 0.2.0 |
| Removed function, changed signature | MAJOR |
0.2.0 → 1.0.0 |
| Pre-release / beta | — | 1.0.0-beta.1 |
Version ranges in sno pkg add
sno pkg add my-pkg@^1.0 # compatible with 1.x.x (default)
sno pkg add my-pkg@~0.2 # compatible with 0.2.x
sno pkg add my-pkg@1.2.3 # exact version
5. Capabilities & safety metadata
The [package.capabilities] section in sno.toml declares what system resources your package accesses. This metadata is shown in the registry and enforced in --untrusted mode.
[package.capabilities]
network = false # no outbound HTTP/TCP
fs_read = false # no file system reads
fs_write = false # no file system writes
exec = false # no subprocess execution
If your package uses http_get or tcp_connect, declare network = true. If it calls file_read, declare fs_read = true.
Being honest about capabilities builds trust with users. The registry displays a capabilities badge on each package page:
LLM use_cases metadata
The [package.use_cases] section helps MCP-connected LLM agents discover your package for relevant tasks:
[package.use_cases]
examples = [
"Parse NMEA GPS sentences from serial port",
"Convert WGS-84 coordinates to local grid",
"Compute distance between two GPS waypoints"
]
When a developer asks their LLM “how do I work with GPS data?”, the MCP server will surface packages whose use_cases match the query.
Quick reference
Using packages
sno pkg search <query>
sno pkg add <name[@ver]>
sno pkg add ./local-path
sno pkg list
sno pkg remove <name>
Publishing
sno pkg login
sno pkg login --key <key>
sno check lib.sno
sno publish
sno publish --yank <ver>