Skip to content
Rather not run it yourself? OpenRMM Cloud hosts it for you.

Frontend Design Brief — OpenRMM

Use this to design and build the web frontend (e.g. in Claude Design / Claude Artifacts), then wire it to the Go backend in this repo. It is self-contained: product context, screens, design language, and the full API contract.


OpenRMM is a self-hosted Remote Monitoring & Management tool whose primary interface is an AI chat. An IT admin manages fleets of computers in natural language — “install 7-zip on the finance group”, “set up printer X at IP Y on host Z”, “give me a report of offline devices”. The AI inspects the fleet and proposes scripts/actions; a human approves before anything runs. Think “a modern RMM: AI-native, privacy-first.”

IT admins / MSP technicians. The UI should feel modern, fast, dense but calm — closer to Linear / Vercel dashboards than to legacy RMM consoles. Dark-mode first, light mode supported. Keyboard-friendly. Trustworthy: this tool runs code on real machines, so destructive/AI actions must feel deliberate.

  • Layout: left sidebar nav + main content area; the AI chat is a first-class destination (not a hidden widget) and also available as a docked side panel.
  • Color: neutral slate base; one accent (indigo/violet). Semantic colors: green=online/completed, amber=awaiting approval/pending, red=failed/offline, blue=running.
  • Type: clean sans (Inter/Geist). Monospace for scripts, IDs, logs, output.
  • Components: cards, data tables with status pills, slide-over drawers for detail, a prominent diff/preview block for scripts, toasts for async results.
  • Motion: subtle; status transitions animate (awaiting → running → done).
  • Tiles: total devices, online/offline, jobs awaiting approval (highlight), recent failures.
  • Recent activity feed (from the audit log).
  • Quick “Ask the AI” input that opens the chat with the typed prompt.
  • Table: hostname, OS (icon), arch, status pill, last seen.
  • Filters: OS, status, group, tags. Search by hostname.
  • Row click → Device detail drawer/page:
    • Header: hostname, OS, status, last seen; Remote button (provider dropdown: native / terminal / meshcentral) → calls remote API, then opens the returned connect_url (terminal is an elevated shell requiring devices.terminal — see 08-remote-access.md).
    • Tabs: Inventory (pretty-print the JSON), Jobs (this device’s history), Checks and Tasks (what monitors and runs on this machine — its own and those its policies bring — with state and last run; GET /api/devices/{id}/checks and /tasks), Patches, Run script (manual: shell selector + editor → creates an approval-gated job), Notes.

4.3 Jobs & Approval queue ⭐ (the safety-critical screen)

Section titled “4.3 Jobs & Approval queue ⭐ (the safety-critical screen)”
  • Two views: Awaiting approval (default, prominent) and All jobs.
  • Each awaiting job shows: target device, description, the full script in a monospace preview block (dry-run), who/what created it (note ai: prefix for AI-proposed), created time.
  • Actions: Approve (primary, requires a deliberate click/confirm) and Reject. After approve, the row animates to running → completed/failed.
  • Completed jobs show exit code + stdout/stderr (collapsible, monospace).
  • Conversation list (sessions) + message thread.
  • Messages: user, assistant, and tool steps (render tool messages as collapsible “the AI looked up X / proposed job Y” cards — don’t hide them; transparency builds trust).
  • When a reply includes created_job_ids, render an inline “Proposed job” card with the script preview and an Approve/Reject action (deep-links to the job). Make it obvious nothing has run yet.
  • Composer with send; show a typing/working indicator while the loop runs.
  • Filterable table: time, actor, action, target, detail. Read-only.
  • AI provider status (model, base URL — read-only display of what’s configured).
  • API tokens (list/create — when the backend exposes it).
  • Enrollment: button to create an enroll token + the agent install command snippet to copy.
  1. Never present an AI action as already done. AI-proposed jobs are proposals; the UI must show them as pending approval with the script visible.
  2. Approval is deliberate — primary button, ideally a confirm step for destructive-looking scripts.
  3. Show the script before running it (dry-run preview), every time.
  4. Surface the audit trail — make it easy to see who approved what.

Base URL from runtime config.js (default location.origin). All /api/* calls need:

Authorization: Bearer <token>
Content-Type: application/json

Username + password → POST /api/auth/login returns {token, role, permissions}; store it in sessionStorage and attach as the bearer on every /api/* call. See §9 for roles and first-run bootstrap. TOTP 2FA and per-user access scope are backend-enforced. Current limitation: the console card has not yet been adapted to send the password/current-TOTP reauthentication fields required for 2FA setup/rotation/disable; use the API contract in 04 for those flows.

To avoid drift, this brief no longer inlines the endpoint list or the TypeScript shapes. Use the single sources of truth:

Remote providers are native, terminal, meshcentral, and an optional rustdesk (off by default; enable in Settings) — see 08-remote-access.md.

status color
online, completed green
awaiting_approval, pending amber
running, sent blue
failed, offline, rejected red

React + TypeScript + Vite, Tailwind, a component kit (shadcn/ui), TanStack Query for data fetching, a code/diff viewer (Monaco or CodeMirror) for script previews. Polling is fine for the MVP (e.g. refetch jobs every few seconds); a job/result WebSocket can come later.

  1. Login (username + password, or SSO) → Devices list → Device detail (inventory + run script).
  2. Jobs / Approval queue with script preview + approve/reject.
  3. AI Chat with proposed-job cards.
  4. Audit log.

That covers the core loop. The full backend (below) is broader.


Part 2 — Full RMM UI (backend is implemented & verified)

Section titled “Part 2 — Full RMM UI (backend is implemented & verified)”

The backend now includes the “classic RMM” feature set. Design these additional areas. Background and semantics: docs/10-monitoring-policies.md.

  • Login screen: username + password → POST /api/auth/login → store the returned token, role, and permissions; attach as bearer. (POST /api/auth/bootstrap creates the first admin, but only with the server’s RMM_ADMIN_TOKEN — an operator step, not a console screen: an empty instance must not be claimable by whoever opens it first.)
  • Roles are permission sets. The built-ins are readonly, tech, and admin, and custom roles can be managed from Settings → Roles. The UI asks for a display name and generates the technical role key automatically. Hide/disable UI actions by permission key (jobs.create, jobs.manage, alerts.manage, devices.terminal, etc.); the API also enforces this (403). Read the current principal from GET /api/me.

Tree or master-detail of Clients → Sites. Create/delete with clients.manage. Show device counts. From a site, copy an enrollment command (create a site-bound enroll token via POST /api/enroll-tokens {site_id} and show the agent install snippet). Device detail gains a site selector (PATCH /api/devices/{id}/site).

Table (name, category, shell). Editor with a code editor for body (Monaco/ CodeMirror, syntax by shell). “Run on device” action → pick device → creates an approval-gated job. CRUD requires scripts.manage.

  • Per device and per policy: list checks with their live status pill (passing/warning/failing) from the latest result.
  • Create/edit check: type (diskspace/memory/cpuload/ping/winservice/script), type-specific config (path / host / service / inline script), warn/err thresholds, interval. Note the threshold direction per type (disk/mem = alert when low; cpu = alert when high).
  • Check detail: a time-series / history of results (value + status) from GET /api/checks/{id}/results?agent_id=.

List + create/edit tasks (pick a library script or inline; schedule = interval or daily-at-time; enabled toggle). Show last run + link to the jobs it produced (jobs.task_id). Per device and per policy.

  • Policy list; policy detail with its checks and tasks (reuse 10.3/10.4 in “policy mode”), and an Assignments panel: assign to a client, site, or agent. Communicate clearly that assigning to a client/site pushes these checks/tasks to all agents in scope (inheritance).
  • Dashboard-prominent. Table of alerts: severity (info/warning/error), source (check/task/agent), status (new/acked/resolved), message, device, time.
  • Filters by status/severity. Actions: Ack, Resolve (alerts.manage). Alerts auto-resolve when the condition clears — reflect that with live status.
  • Surface the open-alert count as a badge in the nav and on the dashboard.

Users: list/create/disable/delete users with role (users.manage). Disable is the non-destructive counterpart to delete — the row shows the state and the confirmation spells out the difference. Editing a user’s email address takes users.email.manage on top, so those controls are hidden without it. The password field states the whole rule and the create button says why it is disabled, rather than greying out unexplained. Show AI provider + remote provider config (read-only). Enrollment token management.

API tokens / MCP connectors (api_tokens.manage): list/create/revoke API tokens (GET/POST/DELETE /api/api-tokens). On create, show the secret once with a copy button and the /mcp connector URL, so the user can paste both into Claude/ ChatGPT. Explain that the token uses a role, needs mcp.use for MCP, exposes only tools allowed by that role’s permissions, and is revocable.

  • Delete device (DELETE /api/devices/{id}) and delete group (DELETE /api/groups/{id}) require devices.delete / clients.manage and an explicit confirm dialog (type-to-confirm for devices). These are deliberate human actions — never triggered by the AI. Device groups: GET/POST /api/groups, assign via PATCH /api/devices/{id}/group.
  • Approval is mandatory for every script run; the UI never offers a “run without approval” path unless the backend reports it is enabled.

11. Additional API & types — canonical sources

Section titled “11. Additional API & types — canonical sources”

The “classic RMM” endpoints (auth, users, org, scripts, checks, tasks, policies, alerts) are documented in full in 04-api-reference.md, with the semantics in 10-monitoring-policies.md — not duplicated here.

All request/response TypeScript types (User, Client, Site, Script, Check, CheckResult, Task, Policy, PolicyAssignment, Alert, plus Agent.site_id / Agent.description) live in ../openrmm/handoff/apiClient.ts, kept in sync with the running UI. Use that as the source of truth rather than copying types into this brief.

Dashboard · Devices · Alerts · Checks · Tasks · Policies · Scripts · AI Chat · Clients · Audit · Users/Settings. Alerts and the AI Chat are the two attention-grabbing destinations; everything else is management.