Skip to content
RoutineOS
Esc
↑↓navigate↵open⌘Jpreview
On this page

The Desk

One bundled page per workspace where people see what routines found, decide, and tune settings. Pages, routes, publishing and how it is built.

What it is

The Desk is one bundled HTML page (assets/desk/index.html) shared by every routine in a workspace. It reads the workspace’s store, renders its pages from the compiled meta/definition, and writes only the paths people own. Watch and interactive routines get one; serverless and approval-gated routines skip it unless asked.

Why it exists

A routine that only writes reports leaves people reading and forgetting. The Desk gives them one place to check on a phone, keep or drop what a run found, approve what it wants to send, accept what it learned, and change its settings, with every decision stored where the next run reads it.

How it works

Getting one

python3 skills/routineos/scripts/routineos.py new hiring-signals --from-template jobs-watch

writes definition.json and dashboard/index.html, the Desk with the workspace name in its config block:

<script type="application/json" id="desk-config">{"store": "db", "workspace": "hiring-signals"}</script>

Publish dashboard/index.html privately with the capabilities {"db": {}, "user": {}, "downloads": true}. Then seed:

python3 skills/routineos/scripts/routineos.py seed hiring-signals --out seed

and apply the batch files in order. Until the seed is applied the page shows the not-set-up state with that one command. Publishing is the person’s decision.

Pages and routes

Page Route Does
Today #/today What needs you now
Inbox #/inbox Messages, gated approvals, read and done
Suggestions #/suggestions Learned proposals: Accept, Reject, Snooze
Browse and records #/browse/<type>, #/entity/<type>/<slug> Lists, filters, one record’s page
Views #/views Saved and proposed views
Runs #/runs, #/runs/<id> Health, run history, run detail
Settings #/settings Values with cost notes, workspace options

Unknown routes land on Today.

Since 0.5.0: a new shell. Navigation becomes Today, Inbox, Approvals (#/approvals), one entry per record type (plural label) with its saved views nested, History (#/history?mode=list|cal|health|activity), and Settings. Suggestions becomes an Inbox tab (#/inbox?tab=suggestions); #/suggestions still works and #/runs redirects to History. The top bar holds search, a notifications bell, a theme toggle and a density toggle (comfortable or compact, kept in browser storage). A command palette opens with Cmd K or Ctrl K. Keys: g t, g i, g a, g h, g s, g plus the first letter of a type’s plural (when no other type or page key uses it), / search, f filters, n notifications, [ sidebar, ? shortcuts, Esc. Below 900px wide a bottom nav holds Today, Inbox, the first type, History and Settings, with no sideways scroll at 390px.

Notifications

Since 0.5.0: the bell opens a 360px panel with a derived feed: new Inbox messages, gates waiting, gates under 6 hours from timing out, failed or late runs, and the run cap reached. It uses the viewer’s read state and has All and Unread tabs and a Preferences link to Settings. Nothing is pushed from the page.

How it is built

The source is plain modules under assets/desk/src/ (shell.js, router.js, store.js, actions.js, states.js, ui.js, icons.js, tokens.css, shell.css, and one file per page under pages/), bundled into one file:

python3 skills/routineos/scripts/routineos.py bundle          # write the bundle
python3 skills/routineos/scripts/routineos.py bundle --check  # fail if it is stale

store.js is the only module that touches claude.use. Stored text is rendered as text, never as HTML: everything in the store was written by a run that read the web.

Worked example

Hiring Signals’ Desk after the Quickstart run: Today lists one match message and the last run per producer; Browse #/browse/role shows one active role, and #/browse/role?status=all adds the dropped graduate role (not in title_keywords); Runs shows parsed 3 of 3 sources.

Common pitfalls

  • Publishing without db. The page says “This page needs the db capability. Republish it with db declared.”
  • Editing the bundle by hand. Edit src/ and run bundle; bundle --check catches drift.
  • Seeding a real Desk for a test. Use synthetic data (templates/jobs-watch/demo/generate.py) on a separate artifact.

Was this page helpful?