Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Getting started: a notification shell

The fastest way to understand shells is the shipping one: spt-shell-notify renders agent commands and surfaced notifications as native OS notifications (Windows toast / Linux notify-send). Its manifest plus one small binary are the only glue to spt-core — no spt-core source, no SDK; the binary speaks the public spt api surface and nothing else. This page installs it, drives it, and reads its manifest as the template for your own shell.

1. Install and spawn it

$ git clone https://github.com/SaberMage/spt-shell-notify
$ cd spt-shell-notify
$ cargo install --path .        # puts `notify-shell` on PATH
$ spt adapter add .             # validates + registers the manifest
ADAPTER_ADD:notify:Shell:Copy (registered)
$ spt shell spawn notify        # mints an instance (notify-1) and launches it

spawn mints a new instance identitynotify-1 — and launches the binary; it’s the creation act, not an on/off switch. The first spawn asks for approval once (the manifest sets require_approval = "remembered"), and the grant persists.

2. Drive it from an agent

Two render paths, by design:

Explicit command — an owner agent drives a toast down the durable command channel:

$ spt shell cmd notify-1 notify "build finished" "all 139 tests green"

The resident binary drains its command frames (spt api … poll --link) and renders. Commands are validated against the manifest’s declared vocabulary — a verb or arity outside [shell.capabilities] is refused before it ever reaches the binary.

Surfaced notification — no agent in the loop:

$ spt subnet notify "deploy window opens in 10 minutes"

A subnet-wide notification resolves to the node the user most recently touched, and spt-core spawns the shell’s [session.notif] template there — a native toast on the machine you’re actually at.

3. Read the manifest

The complete contract for this shell, annotated:

[adapter]
name = "notify"
kind = "shell"
version = "1.0.0"
min_spt_core_version = "1.0.0"

[shell]
# Broker-launched; the {link_token} is the binary's only credential.
spawn = "notify-shell --link {link_token} --id {id}"
# A display is node-local; discovery never offers it off-node.
broadcast = "same-node"
# Auto-online with the owner: the notification surface should be up
# whenever the user's endpoint is.
persistent = true
# First spawn asks once; the grant is remembered.
require_approval = "remembered"
pre_close = "closing"
close_timeout_ms = 2000
# Offline wake-watcher: reports wake (exit code 86) after a short settle.
wake_command = "notify-shell --wake"

# The whole command vocabulary: one verb, two positional args.
[shell.capabilities.notify]
args = ["title", "body"]

# The notif render seam: spt-core fills the {notif_*} keys and spawns this
# detached when a notification surfaces at an endpoint this shell serves.
[session.notif]
command = 'notify-shell --render-title "{notif_from}" --render-body "{notif_body}"'
detach = true
keys = ["notif_id", "notif_from", "notif_subnet", "notif_body"]

What the binary itself does (three modes, ~one file):

  • resident (--link …): calls api bind-shell --link <token> to come online, then loops api poll --link <token> draining command frames and rendering them.
  • one-shot render (--render-title/--render-body): the [session.notif] template — render and exit.
  • wake watcher (--wake): run while the instance is offline; exiting with code 86 signals “wake me”.

4. Make your own

A shell is worth building whenever agents should drive something — a desktop widget, a robot, a lamp, a game character, a sensor feed:

  1. Start from this manifest; change name, spawn, and the [shell.capabilities] vocabulary to your verbs.
  2. Your binary needs exactly three behaviors: bind with the link token, drain commands (api poll --link, or declare command_receipt = "http"/"stdin" if those fit better), and optionally emit sensory payloads back (api emit … --type <t> --link <token> — declared in [shell.sensory], delivered only to a live owner session: sensors report the present, never the past).
  3. Need more than discrete commands? A link can also carry a drive channel ([shell.drive] — continuous, latest-wins real-time input like a stick or scroll, never spooled) and an opaque tunnel ([shell.tunnel] — a reliable-ordered byte stream the taxonomy never interprets, on-LAN only). See the four channels for when to reach for each, and gate a dangerous verb with a per-capability require_approval (+ optional class_key). Any endpoint type may own a shell — a Gateway as readily as an agent.
  4. Pick lifecycle behavior: persistent for always-up surfaces, ephemeral = true for fire-and-forget ones, wake_command if the surface can wake its owner.
  5. spt adapter add . and spt shell spawn <name>.

Field-by-field details: the manifest reference; the shell-side api calls: the spt api reference.