Runyard Setup

What is Runyard

Runyard is a self-hosted control plane for agent runs. It exposes a capability catalog over MCP, CLI, HTTP API, and a Web Hub; dispatches work to local or remote runners; and stores logs, events, artifacts, approvals, skills, agents, and knowledge centrally. The codebase ships as the smithers-hub package; Runyard is the public product name and the names compose without breakage.

Install

Requirements: Node.js 22.5+ (the server uses --experimental-sqlite), pnpm, and a writable data/ directory.

git clone https://github.com/yolo-maxi/runyard
cd runyard
pnpm install
pnpm build:vendor   # vendors highlight.js + react-flow for the workflow viewer

Public clients can also install the CLI from a running hub with bash <(curl -fsSL https://hub.example.com/install.sh). hub.example.com is just an example domain — use whatever you host on.

Run locally

PORT=43117 BASE_URL=http://127.0.0.1:43117 pnpm start
# server writes data/bootstrap-token.txt on first boot
open http://127.0.0.1:43117/app

Topology options

Runyard is built for one private Hub per company or org. The Hub owns durable state; runners are disposable workers that poll over HTTPS. You can adapt the deployment shape to your threat model and hardware.

Deploy

Auth tokens

Runyard uses long-lived access tokens. On first boot the server writes data/bootstrap-token.txt — that becomes the operator key for Web login, CLI, MCP, API, and runner registration. Issue additional tokens from the Connect tab inside the Hub.

CLI

smithers-hub login --url https://hub.example.com --token shub_...
smithers-hub capabilities
smithers-hub capability prepare-spec
smithers-hub run prepare-spec --input '{"goal":"Prepare a rollout spec"}'
smithers-hub runs
smithers-hub runners
smithers-hub approvals
smithers-hub approve appr_...

Multiple orgs work like git remotes:

smithers-hub login --remote acme --url https://acme-hub.example
smithers-hub mcp install --all --remote acme   # installs as smithers-hub-acme
smithers-hub remote use acme
smithers-hub remotes

MCP config

{
  "command": "smithers-hub-mcp",
  "env": {
    "SMITHERS_HUB_URL": "https://hub.example.com",
    "SMITHERS_HUB_TOKEN": "shub_..."
  }
}

From a running Hub, smithers-hub mcp install --all writes this config into every detected agent — Claude Code/Desktop, Codex, Cursor, Windsurf, Gemini, VS Code.

Runner pool

Runners are stateless processes that poll the Hub for queued work. Each runner advertises a tag set and an optional capacity:

SMITHERS_HUB_URL=https://hub.example.com \
SMITHERS_HUB_TOKEN=shub_... \
SMITHERS_RUNNER_NAME=hetzner-vps-runner \
SMITHERS_RUNNER_LOCATION=vps \
SMITHERS_RUNNER_TAGS=linux,node,git,shell,web,smithers \
SMITHERS_RUNNER_CAPACITY=4 \
smithers-hub-runner

Telegram approvals

Approval notifications are designed for a private operator DM. Configure TELEGRAM_BOT_TOKEN plus TELEGRAM_APPROVAL_CHAT_ID or SMITHERS_TELEGRAM_APPROVAL_CHAT_ID. Legacy TELEGRAM_CHAT_ID/TELEGRAM_THREAD_ID remains a fallback when no private approval chat is set. Approve/reject/request-changes from Web, API, CLI, MCP, or the Telegram buttons; the decision is recorded once in the Hub regardless of surface.

Environment variables

Required for production:

Optional:

Runner-side variables (used by smithers-hub-runner):

Security model

Verification

pnpm test                       # full Node test runner
curl -s http://127.0.0.1:43117/healthz   # liveness
curl -s http://127.0.0.1:43117/readyz    # DB warm
curl -s http://127.0.0.1:43117/llms.txt  # agent discovery copy
curl -s http://127.0.0.1:43117/openapi.json | head

Manual checks after install:

  1. Log in to /app with the bootstrap token.
  2. Run Prepare Spec.
  3. Start a runner and confirm the run succeeds.
  4. Open the run detail page and download the generated artifact.
  5. Run Implement; approve it via Web or MCP; confirm it queues and executes.
  6. Configure a local MCP client with smithers-hub-mcp and call list_capabilities.

Open source & contributions

Every console page, run, workflow, agent, skill, knowledge entry, run artifact, and approval has a stable URL — paste it into chat or docs and it survives reload. Each card and detail view shows a 🔗 button to copy that link to your clipboard. Examples:

/app#runs                                 # all runs (home)
/app#runs/<id>                            # one run's detail
/app#runs/<id>/logs                       # jump to the log timeline
/app#runs/<id>/artifacts                  # jump to artifacts
/app#runs/<id>/artifacts/<artifact-id>    # one artifact inside its run
/app#workflows/<slug>                     # workflow detail (description, agents, runs)
/app#workflows/<slug>/run                 # workflow detail with the Run form open
/app#workflows/<slug>/runs                # latest runs for this workflow
/app#workflows/<slug>/edit                # workflow detail with the Edit modal open
/app#agents/agents/<slug>                 # a specific agent
/app#agents/skills/<slug>                 # a specific skill
/app#agents/knowledge/<slug>              # a knowledge entry
/app#approvals/<id>                       # an approval
/app#tokens | #runners | #audit | #connect | #settings

The same URLs come back as deepLink fields on most API responses (runs, capabilities, artifacts, approvals) so MCP/CLI clients can hand operators a clickable link with zero extra work.