Reports that update themselves. A dashboard of living widgets, each regenerated on schedule by a Claude Code routine and published to a GitHub repo you own.
Every developer keeps a handful of reports that only stay current while someone refreshes them by hand: opening the tool, running the update, shipping the change. The daily plan, the review queue, the status update, the changelog. They rot the moment the author gets busy.
Steward hands the chore to routines. Each widget on the dashboard is a small self-contained HTML artifact that a scheduled Claude Code routine regenerates and publishes.
Your data is yours. There is no database and no artifact host. Routines, layouts, and published widgets all live in a private GitHub repo you own. The app is a stateless renderer working with your token, so privacy is GitHub's repo boundary rather than app logic. Share access with whoever you like; leaving is deleting a repo.
GitHub is the whole backend:
- This repo (shared): the web app, the schemas, the contract skills,
and the built-in routine templates (
templates/routines/). Team-visible; never holds user data. - Your data repo (
steward-data-<login>, private): created for you from a template on first sign-in.mainholds your config; theartifactsbranch holds your published widgets atw/<slug>/index.html.
The loop:
- Add a routine in the UI. Describe the widget or start from a template, name it, pick a size, a schedule (or manual), and a host. Sync commits it to your data repo.
- A run fires, from a cloud schedule, local launchd, an update-button
click, or
steward run <slug>in a terminal. Every path is one stable line: "Run the steward routine<slug>— follow therun-routineskill." - The routine publishes. It writes a self-contained, responsive HTML
artifact (docs/widget-standard.md) and
pushes it to your
artifactsbranch. Publishing is the git push. - The dashboard renders. The app fetches your artifacts with your token and shows each in a sandboxed iframe; the last commit becomes its "Ran 2h ago" freshness readout.
Deeper reading: CONTEXT.md and docs/widget-standard.md.
Prerequisites: a GitHub account; Claude Code (for routines to run).
- Open the app and sign in with GitHub (scopes:
repo,read:user). - First run: accept the wizard that creates your private
steward-data-<you>repo from the template. - Add a routine (prompt → name → size → schedule/host) and Sync.
- Enact it. Each widget card prints the exact line:
npx @devord/steward sync --apply --repo <owner>/steward-data-<owner>. It creates the cloud routine or launchd agent and reconciles drift on every later run. Scheduled-local (launchd) routines want a stable install:npm i -g @devord/steward. - Missed a trigger? Mint one with
npx @devord/steward trigger <slug> --repo <owner>/steward-data-<owner>. - Widgets refresh on their own from then on; stale or never-run widgets say so on the card.
Requires Node ≥ 24 and pnpm 10.
pnpm install
pnpm exec lefthook install # once, after cloning (ignoreScripts blocks auto-setup)
pnpm dev # app on http://localhost:5173
pnpm check # oxlint + oxfmt + typecheck in one pass
pnpm test # vitest via turbo
pnpm build # production buildWorkspace layout:
| Path | What |
|---|---|
apps/web |
React Router v8 app (framework mode, SSR, Tailwind 4) |
packages/schema |
zod schemas for routines/dashboards/templates; buildless, source-exported |
packages/cli |
the @devord/steward routines CLI; bundled + published to npm |
.claude/skills |
the contract skills (run-routine, widget-artifact, publish-widget) |
templates/ |
the data-repo template and the built-in routine templates |
docs/ |
ADRs, widget standard, roadmap |