Documentation

Feather wire protocol

JSON-RPC v1 reference for subprocess Feathers.

Subprocess Feathers communicate with toowl over newline-delimited JSON. Each line is one envelope.

Handshake

  1. Host sends Hello { protocol: 1 }.
  2. Feather replies HelloOk { protocol: 1 }.
  3. Host sends Manifest; feather returns full PluginManifest.
  4. Host sends BuildSidebar { ctx } on each Perch frame; feather returns optional View tree.
  5. Host sends OnEvent notifications (fire-and-forget) for clicks, palette actions, ticks.

Envelope shapes

{"kind":"req","id":1,"body":{"method":"hello","params":{"protocol":1}}}
{"kind":"resp","id":1,"body":{"result":"hello_ok","value":{"protocol":1}}}
{"kind":"event","body":{"event":"shutdown","params":{}}}

Host → feather methods

MethodPurpose
helloProtocol version negotiation
manifestFetch manifest (capabilities, id, name)
build_sidebarBuild Perch View tree

Feather → host reverse calls

MethodCapability required
host_spawn_panepane_spawn
host_inject_panepane_inject
host_open_urlnetwork
host_http_getnetwork
host_show_banner / host_dismiss_bannernotify
host_read_filefs_read
host_watch_pathfs_watch
host_state_get / host_state_set(always allowed)

Manifest on disk

id = "my-feather"
name = "My Feather"
version = "0.1.0"
program = "./my-feather"
capabilities = ["pane_spawn", "notify"]

The subprocess sends its authoritative manifest over the wire at handshake; the TOML file controls spawn only.

Starting from scratch

A subprocess Feather is any executable that speaks this protocol on stdin/stdout — Python, Node, Go, Rust, a shell script, whatever you like. The minimum is a directory in ~/.config/toowl/plugins/ containing the manifest TOML above plus your executable. Handle initialize, reply with your manifest, then answer render; everything else is optional.

See also Authoring Feathers and the Aviary.