The only way
for Claude to do UI.

Author components with zero boilerplate. Loom is the first UI language optimized for both human maintainability and agentic development.

button.loom
- props
  label: string
  variant: 'primary' | 'ghost' = 'primary'

- ts
  const isPrimary = variant === 'primary'

- pug
  button.btn
    :class { 'btn--ghost': !isPrimary }
    ::
      padding 10px 20px
      border-radius 8px
      background {isPrimary ? '#7c3aed' : 'transparent'}
    {label}
export function Btn({ label, variant = 'primary' }: {
  label: string
  variant?: 'primary' | 'ghost'
}) {
  const isPrimary = variant === 'primary'
  return (
    <button
      className={`btn${!isPrimary ? ' btn--ghost' : ''}`}
      style={{ padding: '10px 20px',
        background: isPrimary ? '#7c3aed' : 'transparent' }}
    >
      {label}
    </button>
  )
}
The Problem

Same component.
96% fewer tokens.

Traditional frameworks require heavy boilerplate, saturating context windows. Loom eliminates the noise, giving AI agents more room to reason.

ReactCard.tsx
import { useState } from 'react'

interface Props {
  name: string
  role: string
}

export function Card({ name, role }: Props) {
  const [liked, setLiked] = useState(false)
  return (
    <div className="card">
      <h3>{name}</h3>
      <span>{role}</span>
      <button
        onClick={() => setLiked(!liked)}>
        {liked ? '♥' : '♡'} Like
      </button>
    </div>
  )
}
VueCard.vue
<script setup lang="ts">
import { ref } from 'vue'
defineProps<{
  name: string
  role: string
}>()
const liked = ref(false)
</script>

<template>
  <div class="card">
    <h3>{{ name }}</h3>
    <span>{{ role }}</span>
    <button @click="liked = !liked">
      {{ liked ? '♥' : '♡' }} Like
    </button>
  </div>
</template>
SvelteCard.svelte
<script lang="ts">
  export let name: string
  export let role: string
  let liked = false
</script>

<div class="card">
  <h3>{name}</h3>
  <span>{role}</span>
  <button
    on:click={() => liked = !liked}>
    {liked ? '♥' : '♡'} Like
  </button>
</div>
Loom collapses all three into one & cuts tokens by 96%

card.loom

14 lines · 35 tokens · Infinite Context

The Solution

One .loom file.
Any framework.

Explicit zones cleanly separate props, logic, and template. By eliminating boilerplate, Loom accelerates iteration for both humans and AI agents.

card.loom14 lines
- props
  name: string
  role: string

- ts
  const liked = ref(false)

- pug
  div.card
    h3 {name}
    span.role {role}
    button
      @click liked = !liked
      {liked ? '♥' : '♡'} Like
- propsComponent interface

Typed props with optional defaults. Compiles to framework-native declarations — no boilerplate.

- tsLogic

Standard TypeScript. Import any library. Loom wires reactivity per-framework automatically.

- pugTemplate

Indentation-based markup. :: for scoped styles, @event for handlers.

- genericsTypeScript generics

Generic type parameters for type-safe, reusable component APIs.

For AI Agents

Built for the
agent era.

loom-llm gives agents a structured projection of your component — block IDs, symbols, markup tree — so they read and patch only what they need.

What your agent sees
loom-llm show --mode outline
# File: src/Counter.loom
Component: Counter
Mode: outline
Token Estimates: source=68, outline=41, edit=18

## Diagnostics
- none

## Symbols
- imports: none
- props: title, initialCount
- state: count
- computed: isBig
- elements: div, h2, button, span, p

## Blocks
- [props:0] 2 props
- [state:0] 1 state var: count
- [computed:0] 1 computed: isBig
- [markup:0] div.counter-card

## Markup Tree
- [markup:0/div:0] div.counter-card
  - [markup:0/div:0/h2:0] h2
  - [markup:0/div:0/button:0] button (@click)
  - [markup:0/div:0/span:0] span
  - [markup:0/div:0/if:0] if isBig
What you see
Counter.loom
- props
  title: string
  initialCount: number = 0

- state
  count: number = initialCount

- computed
  isBig = count > 10

- pug
  div.counter-card
    ::
      padding: 1.5rem
      border: {isBig ? 'red' : '#ddd'}
    h2 {title}
    button
      @click
        count++
      + Increment
    span Current: {count}
    if isBig
      p.warning BIG NUMBER!
What is outputted
import { useState, useMemo } from 'react'

export function Counter({
  title, initialCount = 0
}: { title: string; initialCount?: number }) {
  const [count, setCount] = useState(initialCount)
  const isBig = useMemo(
    () => count > 10, [count]
  )
  return (
    <div className="counter-card"
      style={{ padding: '1.5rem',
        border: isBig ? '1px solid red'
          : '1px solid #ddd' }}>
      <h2>{title}</h2>
      <button
        onClick={() => setCount(c => c+1)}>
        Increment
      </button>
      <span>Current: {count}</span>
      {isBig && <p className="warning">
        BIG NUMBER!
      </p>}
    </div>
  )
}
loom-llm show --mode outline
Agent reads 41 tokens, identifies [computed:0]
Sends replace-block patch JSON
File updated & verified
Token Efficiency

Use fewer tokens.
Do more.

Context tokens needed for an agent to understand and edit the same component, across tools.

LangChain Agents
~510 tok
OpenAI Function Call
~420 tok
Anthropic Tool Use
~380 tok
loom (full source)
~68 tok
loom-llm outline
~41 tok
loom-llm edit (focused)
~18 tok 15× less than LangChain
* Tokens estimated using GPT-4 tokenizer for the same counter component task.
Features

Built for how you
actually work.

From incremental adoption to full-stack SSR — Loom fits your workflow.

Write once, deploy anywhere

One .loom file compiles to idiomatic React, Vue, or Svelte. No rewrites when your stack changes.

ReactVueSvelte

Zero runtime overhead

Compiles to native framework code at build time. No wrapper layers, no abstraction tax.

Incremental adoption

Drop .loom components into any existing React, Vue, or Svelte project. No migration required.

TypeScript-native from the start

Typed props, generics, and full IDE support out of the box. Loom knows your types — and so does your editor.

High-Performance Compiler

Written in Rust to ensure instantaneous compilation. ~28ms builds keep your development loop fast as your project grows.

Automated Migration

Ship with confidence. Our codemod tools automatically transform existing React components into clean Loom zones.

Token Efficiency

Significantly reduce LLM token usage. By compressing component structure, Loom lowers the cost of agent-driven development.

Ready to build
with Loom?

Start writing cleaner components today. Works seamlessly with Vite — drop in the plugin and you're ready to go.

© 2026 Loom. Open source under MIT License.