Skip to the usage guide
inkby Google Labs

Ink Skill.

A Claude Code and Codex skill for UI design: renders JSON specs into interactive terminal UIs with Ink.

  • Web & UI
  • Terminal UI
google-labs-code/design.md · .agents/skills/ink/SKILL.mdSKILL.md
--- name: ink description: Ink terminal renderer for json-render that turns JSON specs into interactive terminal UIs. Use when working with @json-render/ink, building terminal UIs from JSON, creating terminal component catalogs, or rendering AI-generated specs in the terminal. --- ## Quick Start ## Spec Structure (Flat Element Map) ## Standard Components ## Visibility Conditions ## Dynamic Prop Expressions ## Event System
Front matter and section headings read from the upstream file on 2026-09-14 · 9,805 characters in full

01 What it does

What the ink Skill Does in Claude Code and Codex

Summary, workflow and outputs, all read from the skill's SKILL.md.

From the SKILL.mdRead 2026-09-14 · not a recorded run

In the Skill's Own Terms

The skill covers @json-render/ink, an Ink terminal renderer that turns JSON specs into interactive terminal component trees with data binding, visibility, actions and dynamic props. It walks through defining a catalog from the Ink schema with zod, registering only custom components in a registry, and rendering with Renderer inside JSONUIProvider, or the higher-level createRenderer and standardComponents.

Readers learn the flat element map spec format with a root key, the standard layout, content and interactive component sets, state and binding expressions, the event system and built-in setState, pushState and removeState actions, repeat lists, JSONL streaming via useUIStream, provider roles, key exports, and terminal design guidelines such as 80-120 column width.

What it produces

  • An interactive terminal component tree rendered from the JSON spec.
  • An AI system prompt generated from the catalog for spec authoring.
  • A framework-agnostic in-memory StateStore that drives re-renders.
See the example prompt ↗

How It Works

  1. 01
    Define a Catalog from the Ink Schema

    Import defineCatalog from @json-render/core and pass the Ink schema together with the component and action definitions you want to allow.

  2. 02
    Register Only Your Custom Components

    defineRegistry takes the catalog, but the standard component implementations are already built in, so only custom ones are mapped to Ink elements.

  3. 03
    Wrap the Renderer in Providers

    JSONUIProvider supplies the state, visibility, action and focus contexts to the Renderer, which receives the spec and the registry.

  4. 04
    Author Specs as a Flat Element Map

    The spec carries a root key naming the first element and an elements map of typed nodes with props, children and optional event bindings.

  5. 05
    Bind Props with Expressions

    Any prop value can resolve at render time from state, repeat items, conditions or string templates instead of being hard coded.

  6. 06
    Stream Specs Progressively

    useUIStream consumes JSONL patch streams from an API endpoint and exposes spec, send and isStreaming to the caller.

02 Find your fit

When to Use the ink Skill

Use the ink skill in Claude Code or Codex when the job is UI design of this kind. Fit and limits below are taken from the skill's own file.

Good Fit

  • Teams building terminal UIs from JSON specs with @json-render/ink.
  • Projects that need their own terminal component catalog in addition to the standard set.
  • Rendering AI-generated specs in the terminal instead of a browser.
  • Interactive terminal forms with inputs, selects, toggles and confirmation prompts.
  • Streaming generated specs progressively from an API endpoint into the terminal.

Know the Boundaries

  • It is not a browser or React DOM renderer; the output is an Ink terminal component tree.
  • Wide horizontal main layouts are discouraged in favour of vertical structure.

What to Provide

  • A JSON specThe Renderer is handed the spec object together with the registry it should resolve components against.
  • A catalogcreateRenderer is built from a catalog module, which is spread together with standardComponents and any overrides.
  • Component implementationsCustom components are mapped to Ink functions inside defineRegistry, receiving props from the spec.
  • Custom component schemasEach custom component entry declares its props with a zod object so the catalog stays type-safe.
  • Initial state valuesControlled state such as the active tab is passed to the renderer as a state prop.

03 Inside the skill

Rules the ink Skill Gives Claude Code and Codex

8 concrete instructions, defaults and limits the SKILL.md sets for the agent — the part of the file that changes the result.

  1. Layout Defaults to Row

    Use Box for layout with flexDirection, padding and gap; unless you set it, flexDirection is row, which surprises people expecting column.

  2. No statePath for two-way Binding

    Components must not take a statePath prop for binding; put the binding expression on the natural value prop of the form component instead.

  3. Newline Only Inside a Column Box

    The Newline component inserts blank lines and must be placed inside a Box whose flexDirection is column.

  4. Design for 80-120 Columns

    Terminal width is roughly 80-120 columns, so prefer vertical layouts with flexDirection column for the main structure.

  5. Use Named Terminal Colors

    Colours should come from the named terminal palette: red, green, yellow, blue, magenta, cyan, white, gray.

  6. External Store Overrides Props

    When a StateStore is passed to StateProvider or JSONUIProvider, initialState and onStateChange are ignored, so the store is the single source of truth.

  7. borderStyle for Grouping

    Use the borderStyle prop on Box for visual grouping; the file names single, double, round and bold as the options.

  8. Tabs Drive multi-view Layouts

    For multi-view UIs use Tabs and attach visible conditions to the child content rather than rendering separate specs.

04 Put it to work

Install ink in Claude Code or Codex

One npx skills add command, then a first task in your agent and a checklist for the result.

Add ink to Claude Code, Codex or Your Agent

Run in your project; the installer asks which agent to add it to.

Terminal
npx skills add https://github.com/google-labs-code/design.md --skill ink

Generic skills CLI form for .agents/skills/ink/SKILL.md; the repository may document its own path.

Give the Skill a First UI Design Task

Written in the skill's own terms; replace the bracketed parts with your material.

Starter prompt
Build a terminal dashboard spec for [project name] using the Ink schema. Use a Box with flexDirection column containing a Heading, a Divider, a Table of [rows], and a StatusLine. Add a Tabs component bound with $bindState to /activeTab, show each view through a visible condition, and wire a ConfirmInput to a setState action that flips /confirmed.

Source: written from the SKILL.md in the skill's own terms.

Check the First Result

What the SKILL.md itself says a correct result looks like:

  • Convert the flat element map with flatToTree to confirm every element resolves into the tree.
  • Read a single value back with useStateValue when verifying that bindings point at the right path.
  • Confirm conditional sections actually toggle by relying on VisibilityProvider's state-driven rendering.
  • Write to the external store and confirm the terminal re-renders automatically.
  • Verify two-way bindings go through useBoundProp with a $bindState or $bindItem expression.
  • Check that ProgressBar values stay inside the 0-1 range.

In OpenDesign import ink from its SKILL.md link: Plugins → Add → Skill → Import from link, then pick it in the top bar.

05 Open source, traceable

Source, License and Verification

Where this page's facts come from, and when they were last checked.

Skill file
.agents/skills/ink/SKILL.md Content checksum recorded at verification; commit 9bf8eae
License
Apache-2.0 From LICENSE.
Repository stars
27,894 GitHub snapshot taken 2026-09-14 for the whole google-labs-code/design.md repository. Not a rating or usage count for ink.
Verified by OpenDesign
2026-09-14 Source file, path, license text and star count were checked. Not bundled in OpenDesign main (checked 2026-08-28); a live run has not been recorded on this page.

Inside the SKILL.md

  1. Quick StartImports, catalog creation, a custom component registry, and the provider-wrapped Renderer.
  2. Spec Structure (Flat Element Map)The root plus elements JSON shape, with typed nodes, props and children.
  3. Standard ComponentsLayout, content and interactive components listed with their events, variants and options.
  4. Visibility Conditionsvisible syntax using $state, eq, not, and the $and and $or combinators.
  5. Dynamic Prop Expressions$state, $bindState, $bindItem, $cond and $template, plus the no-statePath rule.
  6. Event Systememit fires named events that map to actions through the element's on field.
  7. Built-in ActionssetState, pushState and removeState are handled automatically with statePath params.
  8. Repeat (Dynamic Lists)repeat renders a state array, with $item and $index available inside children.
  9. StreaminguseUIStream progressively renders specs from JSONL patch streams.
  10. ProvidersSix providers, from StateProvider and ActionProvider through to the combined JSONUIProvider.
  11. createRenderer (Higher-Level API)Creates a component from a catalog with standardComponents and all providers built in.
  12. Terminal UI Design GuidelinesConventions for layout, width, borderStyle, colors, headings, tabs, sparklines and charts.
The Skill's Own Description
“Ink terminal renderer for json-render that turns JSON specs into interactive terminal UIs. Use when working with @json-render/ink, building terminal UIs from JSON, creating terminal component catalogs, or rendering AI-generated specs in the terminal.”

Front-matter description from SKILL.md. The full file is about 9,805 characters. Read the full file on GitHub.

06 Before you install

Questions About the ink Skill

Answers come from the SKILL.md as read on 2026-09-14, not from a recorded run.

What does the spec look like?

It is a flat element map: a root key names the first element, and an elements object holds every node with its type, props and children array.

Can I plug in my own state management?

Yes. Pass a StateStore to StateProvider or JSONUIProvider for controlled mode, and then initialState and onStateChange are ignored.

Does this render in a browser?

No. It is an Ink terminal renderer, so the result is an interactive terminal component tree rather than a DOM tree.

Can a model generate the specs for me?

Yes. The ./server export turns your catalog into an AI system prompt, and useUIStream streams the resulting JSONL patches as they arrive.

Ink

Run ink on a Real UI Design Task.

Download OpenDesign, import ink from its SKILL.md link, paste the prompt above, and read the plan before the result.

Terminal
npx skills add https://github.com/google-labs-code/design.md --skill ink

OpenDesign Desktop

One design system. Every output unmistakably your brand

Inside the full Vibe Design Workspace, use the same brand rules across websites, slide decks, interactive prototypes, dashboards, images, and HTML video. Connect Codex, Claude Code, Cursor, and other coding agents already on your computer, then create locally for free.

  • Web, slides, prototypes, dashboards, images, and video
  • 140+ design systems, plus the full template and skill library
  • Connect local Codex and 21+ coding agents · Free to use
Download free

Available for macOS and Windows