Loom for CTOs: govern the interface your AI tools write

Your teams now ship interface written by AI coding agents. Without the design system in their context, that interface drifts as fast as the agents can write it. Loom keeps it on-system: agents get the real system, their output is checked, and every change reaches your repository as a pull request your engineers review.

AI tools write interface faster than anyone can review it

AI output multiplies inconsistency. Each agent produces plausible code. Across teams, that becomes many local versions of the same components, raw values instead of tokens and accessibility gaps, all at a speed review cannot match.

The design system is not machine-readable. Rules live in documentation and in people's heads. Linters cover a small part. Agents cannot read the rest.

Every tool wants your code in its cloud. New platforms ask for broad access and keep your system in their own format. Leaving becomes expensive.

The model choice keeps changing. You do not want governance that only works with one assistant or one provider.

A small team carries a large system. In the zeroheight Design Systems Report 2026, 16% of design systems are run by one person and 56% of teams name staffing as their biggest challenge.

zeroheight Design Systems Report 2026 (survey of 147 practitioners), figures as published in zeroheight's launch webinar.

Loom keeps AI-written interface on-system, in your repository

Agents get the real system, and a verifier

Any agent that speaks MCP gets 17 tools to search the system, read contracts and tokens, export the system as one DESIGN.md file, check a composition, audit code and propose changes. The checks are deterministic: they give the same answer whichever model wrote the code. Working Working

Governance as code, in your repository

Rules, owners, exceptions, proposals, patterns and deprecations are versioned files in a loom/ folder in your repository. Severity is set per area by its owner; accessibility rules are always errors. Working The rules command runs in any CI from a copy of the repository and fails the job when an error remains. Partial What does not work yet: a packaged CI step. Concept

Your model, your keys

Any agent that speaks MCP can use your system, whichever model it runs on. Working For agents that Loom runs for you, provider setup for Anthropic Claude, OpenAI and any OpenAI-compatible gateway is in development. Concept

Your infrastructure, your repository

The command line and MCP server run on your own machines today. Partial What does not work yet: a packaged CI step and Loom cloud are planned. Concept Output is files your team reviews, or draft pull requests; Loom never merges. Partial What does not work yet: automatic pull requests have been tested against simulated hosts, not a client repository.

Least-privilege access

The GitHub App asks for three permissions: metadata, code (writing only to Loom's own branches) and pull requests. Each token covers one repository; broader tokens are refused. Partial What does not work yet: the App is not yet registered on GitHub. GitLab and Azure DevOps use the same interface. Partial

Controls you can audit

Network access to the MCP server requires a token of at least 32 characters. Working Repository content in tool results is fenced and marked as untrusted. Working Every tool call is logged with token counts and cost estimates, with caps per run. Working Every draft an agent writes is labelled as AI-generated. Working Engagement working copies are deleted at the end, with a receipt. Partial We do not train models on your data. Our commitment

Autonomy you control, per area

Area owners choose Observe, Suggest (default), Auto with guardrails or Full. Even Full keeps pull requests with passing checks, a hard-deny list, undo, a record and an organisation-wide cap. The mode per area is a record today and the stricter-mode rule is enforced. Partial What does not work yet: agents acting on their own under these modes. Until then, every change waits for a person. Concept

Loom asks for the least access that works

The permissions below are read from the GitHub App's manifest and from the code that requests each token.

What the GitHub App may do, and nothing more

From the code

Opens labelled, AI-disclosed draft pull requests with Loom's design-system changes for human review. Never merges, never changes settings, CI or secrets.

Each operation asks for its own short-lived token, scoped to one repository
OperationCodePull requestsMetadata
Audits and scansreadnoneread
Posting a report on a pull requestreadwriteread
Opening Loom's draft pull requests (on Loom's own branches)writewriteread

Never requested: administration, workflows, secrets, checks write, or merge.

Read from github-app/manifest.json and src/git-host/github-app.ts when this page is built; a unit test checks that every token stays inside the manifest.

The architecture keeps the core neutral

How Loom fits your stack

Diagram

Your side

  • Your repository
  • CI
  • Figma
  • AI assistants

Loom core

technology-neutral

  • Tokens
  • Contracts
  • Rules
  • Layers
  • Governance

Readers and writers

  • React
  • React Native
  • Other stacks Concept

Loom cloud Planned

Today Loom runs where you run it. React and React Native are supported; other stacks are candidates. A hosted Loom cloud is planned.

Recording of real output

A recorded session: a scripted agent against Loom Base, our own design system (MIT), with real server output. The replay types each call as the agent sent it and shows each result after its recorded latency, shortened for the page. Server output is in English.

Agent session · recorded session

  1. Agent

    I need a destructive "delete workspace" action with a confirmation. What does the system have?

  2. Loom · search_system · 145 ms→ search_system({"query":"delete confirm danger","kind":"component","limit":5})

    20 results for "delete confirm danger" (lexical ranking). Top: Dialog (dialog, 0.8, beta), ConfirmAction (confirm-action, 0.46, beta), ToastRegion (toast-region, 0.41, beta), Tag (tag, 0.27, beta), Alert (alert, 0.25, beta)

    • Dialog (dialog, strong, confidence 0.8) — import { Dialog } from "@loom/base/native";• ConfirmAction (confirm-action, partial, confidence 0.46) — import { ConfirmAction } from "@loom/base/native";• ToastRegion (toast-region, partial, confidence 0.41) — import { ToastRegion } from "@loom/base/native";
  3. Loom · get_entity · 34 ms→ get_entity({"id":"Button"})

    Button: Starts an action in the current view: save, publish, open a dialog, run a check.

  4. Agent

    Here is my first draft. It reaches for an MUI Modal, guesses a variant prop, uses two primary buttons and hard-codes a colour and a margin.

  5. Loom · check_composition · 48 ms→ check_composition({"tsx":"import { Card, Button, Heading, Text } from \"@loom/base/native\";\nim…"})

    Off-system: 3 errors, 2 warnings across 6 nodes.

    - [warning] Text has style set: overriding a system component's styling is drift from its contract. → Customise through the component's slots, variants or overridable tokens wit…- [error] Button has no "variant" prop. → Did you mean "tone" ("primary" | "secondary" | "quiet" | "danger")? primary: the one main action in a view; secondary: other actions; q…- [error] <Modal> is not part of Loom Base (imported from "@mui/material"). → Closest system components: AILabel (ai-label), Dialog (dialog), Drawer (drawer). If none fits, draf…
  6. Loom · check_composition · 5 ms→ check_composition({"tsx":"import { Card, Button, Text, Stack, ConfirmAction } from \"@loom/bas…"})

    On-system: 0 errors, 0 warnings across 5 nodes.

    components: Card, Stack, Text, Button, ConfirmAction
  7. Loom · audit_code · 117 ms→ audit_code({"files":[{"path":"src/settings/SettingsPage.tsx","source":"import React from \"react\";\nimport { Button as MuiButton, Dialog…

    Drift found: 11 errors, 11 warnings — 7 colours, 9 dimensions, 1 non-system import, 1 re-implemented component.

    ✗ src/settings/settings.css:2 Hard-coded colour #fffdf8 (background). → Use var(--base-color-palette-cotton-0) ().✗ src/settings/settings.css:5 Hard-coded dimension 16px (padding). → Use var(--base-space-scale-6) (16px).✗ src/settings/settings.css:5 Hard-coded dimension 20px (padding). → Use var(--base-space-scale-7) (20px).
  8. Loom · get_guidelines · 11 ms→ get_guidelines({"topic":"illustration"})

    Guidelines for illustration: missing. 0 sections. Missing: Loom Base has no dedicated illustration guideline. Do not invent one: follow existing foundations, and use propose_change (kind "guideline") to draft it for review.

    missing: Loom Base has no dedicated illustration guideline. Do not invent one: follow existing foundations, and use propose_change (kind "guideline") to draft it for review.
  9. Agent

    Research uploads need a drag-and-drop file area. Nothing in the system does that, so I will draft a proposal rather than ship a one-off.

  10. Loom · propose_change · 399 ms→ propose_change({"kind":"component","title":"FileDropzone","need":"Researchers attach interview recordings and notes to a journey. Set…","…

    Draft component-filedropzone-6af1d4b4 written to drafts/component-filedropzone-6af1d4b4.json (status: proposed, labelled AI-generated, not yet human-reviewed). Intake: extend. 7 existing alternatives listed; impact: 5 declared dependents.

    impact: 5 declared dependents (partial graph)status: proposed; system source modified: false
  11. Loom · check_composition · 69 ms→ check_composition({"tsx":"import { Modal } from \"@mui/material\";\nimport { Button } from \"@loo…"})

    Off-system: 4 errors, 5 warnings across 6 nodes.

    - [warning] Raw <h1> used where the system provides Heading. → import { Heading } from "@loom/base/native";- [error] Button has no "variant" prop. → Did you mean "tone" ("primary" | "secondary" | "quiet" | "danger")? primary: the one main action in a view; secondary: other actions; q…- [error] Button has no "variant" prop. → Did you mean "tone" ("primary" | "secondary" | "quiet" | "danger")? primary: the one main action in a view; secondary: other actions; q…
  12. Agent

    The booking flow needs a date range picker. Does the system have one?

  13. Loom · search_system · 17 ms→ search_system({"query":"date range picker for booking","kind":"component","limit":5})

    No component matches "date range picker". Closest partial matches: ComboBox (combo-box, partial match, confidence 0.24, beta: covers "picker" but not "date range"); FormField (form-field, partial match, confidence 0.24, beta: covers "picker" but not "date range"); LooseThreads (loose-threads, partial match, confidence 0.24, beta: covers "picker" but not "date range"). Logged as an unmet need. If this is a real gap, draft it with propose_change instead of building it off-system.

    • ComboBox — partial match: covers "picker" but not "date range"• FormField — partial match: covers "picker" but not "date range"• LooseThreads — partial match: covers "picker" but not "date range"
  14. Loom · search_system · 14 ms→ search_system({"query":"show an error when payment fails","kind":"component","limit":3})

    51 results for "show an error when payment fails" (lexical ranking). Top: ErrorSummary (error-summary, 0.93, beta), AIStatus (ai-status, 0.74, beta), Alert (alert, 0.74, beta)

    • ErrorSummary (error-summary, strong, confidence 0.93) — import { ErrorSummary } from "@loom/base/native";• AIStatus (ai-status, strong, confidence 0.74) — import { AIStatus } from "@loom/base/native";• Alert (alert, strong, confidence 0.74) — import { Alert } from "@loom/base/native";
  15. Loom · list_unmet_needs · 5 ms→ list_unmet_needs({})

    1 unmet need from 1 request; 0 over the threshold (3 requests from 2+ requesters in 30 days). "date range picker" x1.

    • "date range picker": 1 request(s), 1 requester(s) — Below threshold: needs 2 more request(s) and 1 more client(s) or team(s) within 30 days.

We show our own numbers

  • 17 MCP tools; 5 to 399 milliseconds per call in the recorded session on Loom Base. Working
  • The audit runs on code it was never tuned for: a package it had never seen, scored across eight areas in 2.4 seconds with no configuration. Working
  • 50 of 50 parity tests for components written for React and React Native from one contract. Partial Three components so far, and native tests do not yet run on devices.
  • Two pilots on 25 October 2026 found gaps in the audit on real, private apps; both were fixed the same day, with tests. Working

Speed from AI is an opportunity worth taking. Governing what it writes is what keeps that speed safe.

Questions

Is this a wrapper around a model? No. The core is technology-neutral and deterministic: tokens, contracts, rules, layers and governance, with checks that run without a model.

What happens if we stop using Loom? You keep everything. Tokens, contracts, rules and governance records are files in your repository.

Do you hold ISO 27001 or SOC 2? Not today. We answer security questionnaires directly.

Which stacks? The audit reads React, TypeScript, CSS and plain HTML apps. Loom writes React and React Native. Other stacks are candidates.

What about Figma? Figma stays a source of truth. Loom supports paid Figma plans, Professional and up.

Start with a conversation about your system.

We read your system, show you what we found, and agree with your team what to fix first.