Overhand Beta Install

Docs

Plugins

Small add-ons in a sandbox of their own, installed from a pin you approve.

Small add-ons, kept apart.

  • What one is A folder with a manifest and a script: a check (does your site answer?), a tracker (has the status page changed?) or a notifier. Each runs on its own schedule and reports findings.
  • Where you see them A finding marked bad or warn is a card in Needs you, with its fix as a button: open the page it names, or Run again. Every finding, and each plugin's last run, is in Health under Plugins.
  • Where you manage them Settings, Plugins: install, Approve and run, Pause and Remove. Each acts at once.
  • The kind Every kind runs the same way today: on its schedule, reporting findings. The kind is the label the app shows.

Installed from a pin you approve.

  • A pinned version The source is a git repository at one commit (all 40 characters), or a tarball checked against its SHA-256 before it's unpacked, from an https address or a full path on this computer. Overhand fetches it with none of your git config, so no hook, filter or saved login of yours runs, which also means a private repository needs a local copy.
  • The review There's no plugin store and no review by us yet: the review is yours. Before a plugin runs, Settings shows what it does, its kind, the hosts it reaches, the secrets it asks for and its pin, and nothing runs until you approve it. Your approval holds that exact code: any change to its files stops it until you approve it again, and nothing updates on its own.
  • Secrets A plugin names the secrets it wants. You grant each one by name when you approve it, and it reaches the plugin as an environment variable of that name, read from your secret store at each run.
  • Nothing else on its own A link or a special file in its folder stops the install, and so does a folder over 500 files or 10 MB.

What its sandbox enforces.

  • Enforced, not trusted A plugin runs only inside a sandbox of its own, never without it: of the files on your computer it reads only the system's own programs and libraries, its own folder and a scratch folder that's gone when it ends, and writes only that scratch folder. It has no network of its own: its only way out is Overhand's bridge, which fetches for it only from the hosts its manifest declares, on their usual ports, and refuses the rest. It gets no secret unless you grant that one by name, and runs on its schedule within its time and memory limits, stopped when it goes over. It talks back only in findings, one JSON line each, which Overhand checks before any reaches the app.
  • Where it ends On macOS it's sandbox-exec with a profile that denies everything it doesn't allow; on Linux it's bubblewrap with its own empty network, process and file namespaces. A plugin can still send what it reads, including a secret you granted, to a host it declared, and the bridge checks each host's address before fetching but can't stop that host's DNS from changing right after. It can list the names, never the contents, of the folders above its own. On macOS it can't start another program, and the sandbox still lets it reach the system services Apple's own sandbox profile allows every program; on Linux it can start the system's own programs, inside the same sandbox with no more reach than its own, and write an empty /tmp of its own that's gone when it ends. Where neither sandbox runs, plugins don't run at all.
  • The bridge At most 50 requests a run and 2 MB an answer, each within 15 seconds, never to a private or loopback address. Redirects come back to the plugin, so each hop is checked against its hosts again.

Write one.

  • The manifest overhand-plugin.json at the top of its folder: name, version, line (what it does, in one line), kind (check, tracker or notifier), entry (a .ts, .js or .mjs file), hosts, secrets, everyMin (15 to 1440, 60 if left out), timeoutSec (up to 120, 30 if left out) and memoryMb (64 to 1024, 256 if left out). A host is a public name such as status.example.com: no address, port or local name.
  • It runs on bun With plain fetch, which Overhand routes through the bridge. Packages aren't installed for it: ship what it needs in its folder.
  • It prints findings One JSON object per line: {"title": "…", "line": "…", "severity": "info" | "warn" | "bad", "fix": {"kind": "link", "url": "https://…"} | {"kind": "rerun"}}. Up to 50 a run. Any other line, or a non-zero exit, fails the run, and the app says why.
  • An example packages/core/plugins/site-answers checks that the hosts it declares answer, with tests for the sandbox beside it. Copy the folder, change its host and install it from your own repository.