# Ship a whole program as one binary with synsema build

> Engine, program, modules, templates and assets in a single sealed executable, with a capability ceiling baked in. Nothing to install on the target — deploy it FROM scratch, or hand it to someone as a file.

Published 2026-09-02 · https://synsema.org/blog/ship-one-binary-synsema-build


Distributing a script means distributing a runtime: the right Python, the right Node, the packages,
the environment. `synsema build` removes the runtime from the equation. The output is one file that
contains the interpreter and your program, sealed with a checksum.

## One command

```sh
synsema build agent.syn -o agent                      # this platform
synsema build agent.syn -o agent --include data/       # bundle assets (dirs, one-level globs)
synsema build agent.syn -o agent --cap-set "stdout,net=api.example.com"   # bake a ceiling
synsema build agent.syn -o agent-linux --engine-binary ./synsema-linux-x86_64  # cross, with a donor engine
```

The binary runs your program: its argv is `args()`, the templates it renders and the files you
included are read from the bundle without any `file` capability (they are part of the program),
and a write to a bundled path is refused. It is 30–60 MB, like any static binary — nobody weighs the
Docker CLI.

## The ceiling travels with it

`--cap-set` and `--profile pure` are baked in and cannot be raised from inside. Hand someone a
binary built with `--cap-set "stdout,net=api.example.com"` and that is all it will ever touch,
whatever the code declares. `--profile pure` removes the filesystem, processes, databases and
sockets entirely. A tampered bundle refuses to run.

## Deploy it from nothing

```dockerfile
FROM scratch
COPY agent /agent
ENTRYPOINT ["/agent"]
```

No base image, no package manager, no shell in the container. The engine is still reachable when
you need it — `agent --engine version`, `agent --engine run other.syn` — but `--engine update` is
refused: a built program is rebuilt, not patched in place.

## Servers and desktop apps too

Agents, jobs, CLIs, tools you give to a team — and, since 0.6.16, servers: `synsema build app.syn
-o app --serve --bind 0.0.0.0 --port 8080` bakes the serve runtime and the deployment flags in, and
the serve block's static mounts travel inside the file, so a whole site or [installable app](/blog/installable-app-pwa-native-push)
is one executable. Since 0.6.18 the same command makes desktop apps: `--no-console` and `--icon`
give you a `.exe` with your icon that opens in a browser app window, `--bundle` a macOS `.app`
or a Linux launcher folder — see [Ship your web app as a desktop app](/blog/desktop-app-one-binary-browser-window).

**Try it:** [install Synsema](/install), then `synsema build hello.syn -o hello && ./hello`. The
CLI reference, including the WebAssembly artifacts for browsers and TEEs, is in the
[docs](https://synsema.dev/en/0.6.x/70-cli).

