runseal
keep flows explicit.
operational glue rots: too many environment variables, too many machine-specific assumptions, too much of the flow living in shell history and uncontrolled script stacks. runseal gives the glue one small explicit profile — declared resources, named wrappers, injected env — without becoming a task runner or a secret manager.
env symlink argv deno
quickstart
curl -fsSL https://runseal.perish.uk/manage.sh | shmanage.sh installs linux x86_64 and macos (intel and apple silicon) and links runseal into ~/.local/bin — put that on PATH; windows installs via manage.ps1. every artifact's sha256 sits beside it in checksums.txt. then declare a profile at the repo root (runseal.toml) and every command you run through runseal sees it:
[resources]
root = ".local"
[[injections]]
type = "env"
[injections.vars]
APP_DATA_DIR = "resource://data"$ runseal @resolve resource://data
/home/you/app/.local/data
$ runseal sh -c 'echo $APP_DATA_DIR'
/home/you/app/.local/data
name a flow once and it becomes a verb: a wrapper is a .ts or .sh file under .runseal/wrappers; deno wrappers run under the profile's declared permission policy.
const target = Deno.env.get("APP_DATA_DIR");
console.log(`hello - the profile says data lives at ${target}`);$ runseal :hello
hello - the profile says data lives at /home/you/app/.local/data
routing
the first token decides everything: a bare command runs inside the profile, a :name resolves a wrapper, and an @name runs a runseal-owned command like @profile or @resolve.
resources
resource://ssh/config is a profile-only path literal resolved to an absolute path under the declared root. child commands receive only the resolved path.
wrappers
operator flows are deno .ts wrappers under .runseal/wrappers, executed under a repo-declared permission policy: guard, land, init, release.
forge tools
@tool holds the atomic surface — forgejo, github, and cloudflare helpers — while wrappers bind repo-local policy and flow around those atoms.
the receipt below is one real run of this repo's own gauntlet — these wrappers are repo-authored, not builtins, and the deno ones need deno on the path.
$ runseal :guard
==> negentropy version pin
==> biome
==> tsc
==> vitest
==> deno fmt
==> deno check
==> negentropy
clean