Getting Started
Planck is the reference implementation of Database with Embedded Wasm Runtime: your code runs in the same process as your data, every query is a function call, and the unit of deployment is one binary. Whether you are building a monolith, a set of services, or Self-Contained Systems, each unit is one Planck.
The runtime is a small set of pieces working together: an HTTP listener, a WASM runtime, and change streams. Operational tasks (backup, gc, WAL truncate, stats, export, import) are scheduled and run from workbench, which is the control plane. Do note that restore is driven from planctl, not workbench. Replication is its own continuous path between primary and replica, so it is not a scheduler task.
This page walks you from zero to a running host, and then through scaffolding and deploying your first service. On first install, kindly read it top to bottom. After that you can come back to specific sections as and when you need them.
What you're installing
One tarball (zip on Windows) ships three binaries plus a WASM runtime library:
planck: the storage engine, HTTP listener, WASM runtime, and change streams.workbench: the control plane. It owns identity, supervision, the query editor, the deploy receiver, and the scheduler that drives operational tasks against each connected planck. It listens on2369by default.planctl: the CLI you will use for host setup, project scaffolding, and deploys.
A libwasmer shared library sits next to the binaries. planck loads the same at runtime when an app hosts WASM. planctl deploy copies it into each deployed app's directory, so the running instance always finds it as a sibling.
Download
Pick the archive that matches your machine from the releases page.
macOS
macOS is a local / dev target, so install under your home directory, with no sudo and no /opt. ~/.planck/bin is exactly where planctl system init looks for the binaries.
mkdir -p ~/.planck
tar -xzf ~/Downloads/planck-0.1.0-macos-arm64.tar.gz
-C ~/.planck --strip-components=1Add the bin directory to your shell rc (~/.zshrc):
export PATH="$HOME/.planck/bin:$PATH"Linux
Linux is the production target, so install under /opt/planck:
sudo mkdir -p /opt/planck
sudo tar -xzf ~/Downloads/planck-0.1.0-linux-amd64.tar.gz
-C /opt/planck --strip-components=1Add the bin directory to your shell rc (~/.bashrc):
export PATH="/opt/planck/bin:$PATH"Reload your shell, and then check that the binaries are on PATH:
which planck planctl workbenchWindows (PowerShell as Administrator)
Expand-Archive -Path "$HOME\Downloads\planck-0.1.0-windows-amd64.zip
" -DestinationPath .
New-Item -ItemType Directory -Force -Path 'C:\Program Files\Planck'
Move-Item .\planck-0.1.0-x86_64-windows\bin 'C:\Program Files\Planck\bin'planctl system init expects the binaries at C:\Program Files\Planck\bin. Then open Advanced System Settings, go to Environment Variables, and add C:\Program Files\Planck\bin to both the User and System Path entries.
Initialize the host
Before you can deploy anything, you need a workbench (the control plane) and a system database running on this host. One command sets up both:
planctl system initWhat system init does:
- Lays out the data directory under the OS-specific install root (
$HOME/.planckon macOS,/opt/planckon Linux,C:\Program Files\Planckon Windows). - Drops a default
config.yamlfor workbench. (Config is YAML, always. There are no env-var overrides.) - Brings up the system database on port
23469. - Registers
planckandworkbenchas OS-managed services (launchd on macOS, systemd on Linux, or the Windows Service Manager) and starts them.
The install root and service manager are chosen automatically by the host OS, and there is no flag to override the same. (On macOS it registers launchd daemons too; it does not spawn the processes directly.)
Bring everything up:
planctl system startThe workbench listens on http://127.0.0.1:2369 by default. Open that in a browser and log in as the admin user with the built-in default admin key, and then rotate it immediately. The default is well-known and baked into the engine, so do not leave it as is.
Other lifecycle commands you will want:
planctl system stop # stop everything supervised
planctl system start # bring it all back up
planctl system deinit # unregister services; binaries and data files stay on diskConfigure a deploy profile
planctl deploy talks to a workbench. It picks the target from ~/.planctl/config.yaml. The file declares one or more profiles, and each profile lists the workbench nodes it should reach.
For a local install, this much is enough:
profiles:
- name: dev
nodes:
- server: http://127.0.0.1:2369
uid: admin
key: <paste-the-admin-key-here>Every command that hits a workbench takes --profile <name>.
Your first service
Scaffold a hypermedia monolith. It is the fastest way to see the whole stack working end to end:
planctl new mystore --type hda --arch mono
cd mystoreThe four template combinations:
| Type | Arch | What you get |
|---|---|---|
hda | mono | Server-rendered HTML (datastar) + WASM app hosted by planck. One deployable. |
hda | micro | Shell binary, per-feature WASM services, plus an SSE service for live updates. |
spa | mono | Vue 3 SPA + single JSON API + WASM app. One deployable. |
spa | micro | Vue 3 SPA + per-feature JSON services + SSE service. |
Templates do not ship with a reverse proxy, and planctl new does not pick one for you. In dev, the shell, SSE service, and any per-feature services each bind their own port, and the browser reaches them directly via CORS. In production, drop in your own Caddyfile, nginx.conf, or Traefik config.
Before the first deploy, set the ports. The scaffolded app/db.yaml (planck wire port) and app/service.yaml (user-facing HTTP port) both ship as 0, and the pre-deploy validator rejects 0. As such, give each a unique non-zero port.
Now deploy it to the workbench you brought up earlier. planctl deploy builds, uploads, and restarts the supervised processes in one step, so you need not run zig build first. Pick the target flag that matches whatever has changed.
Deploy just the app (mono = WASM hosted by planck; micro = native shell binary):
planctl deploy --app --arch mono --profile devDeploy a single service by name (micro projects only):
planctl deploy --service orders --arch micro --profile devDeploy just the SSE subproject (handy for fast iteration when you are tweaking templates or topic logic and do not need to rebuild the app):
planctl deploy --sse --arch mono --profile devDeploy everything (the app, every services/* for micro, and the SSE subproject if the project has one):
planctl deploy --all --arch mono --profile dev--all runs the targets in order: --app, then each --service <name> (micro), and then --sse last so that the topic is alive before browsers connect. For a brand-new mono project this is the simplest first deploy. After upload, workbench restarts the supervised processes.
Once that returns, your app is live. Open it in a browser, or hit a route with curl, on the HTTP port you set in app/service.yaml (e.g. 3010):
curl -k https://127.0.0.1:3010/The -k is needed because of the self-signed cert. From the workbench UI on 2369 you can also browse the schema, run PQL queries against the app's data, and watch live stats.
A taste of the code
Every HTTP route in a Planck app is a handler with the same signature:
fn handle(ctx_ptr: ?*anyopaque, allocator: std.mem.Allocator, req: *const Request, res: *Response) !void {
// ...
}Responses have a small, deliberate surface: html, json, and write. There is no render method.
A typical hypermedia handler renders a ZSX fragment and writes it back as HTML:
var out: std.ArrayList(u8) = .empty;
try fragment.render(&out, allocator);
try res.html(out.items);Queries are built with PQL. You construct a query against the in-process client and chain operators:
var q = try planck.Query.initWithAllocator(client, allocator);
const tasks = try q
.where("status", .eq, "open")
.orderBy("created_at", .desc)
.limit(20)
.skip(0)
.select(&.{ "id", "title", "status" })
.run();.where(field, op, value), .orderBy, .limit, .skip, .select, .run. That is the whole surface, nothing more.
Where to go next
- Add a feature or service to the project you just scaffolded with
planctl add. - PQL reference for the full operator set and the change-stream API.
- ZSX guide for the template language and how fragments are generated.
- Workbench tour for the supervision, backup, and identity UIs.
Welcome to Planck. Build something small first; the stack rewards iterating in tight loops.