Skip to content

About

Iris: live, interactive UI in bb chat. Agents draw charts, tables, plans, diffs, test runs, pickers and small apps in your theme.

Topics

Resources

Stars

5 stars

Watchers

1 watching

Forks

Repository files navigation

Iris

Agents answer in live cards you can use, not walls of text.

Latest release Needs bb 0.48 or later Apache-2.0 license Listed in the BB Community marketplace

Iris: live, interactive UI in your bb chat. Cards for a migration forecast, a ranked decision and session spend

Website · Playground · Install · Components · Live data · For agents

Iris is a bb plugin that lets agents answer with live, interactive UI instead of walls of text. An agent writes a short ```iris block, and bb draws it as a real card inside the reply: charts you can hover, sliders that recompute, tables you can sort, test runs that fill in while they run, pickers that wait for your answer. Every card wears your bb theme and follows it when you switch.

A bb thread where an agent answers with Iris cards: the person hovers a latency chart, drags a what-if slider, and tunes the weights of a decision until the ranking changes
A real bb thread at 60 fps: the person hovers a chart, drags a what-if slider and tunes a decision. Watch it in full resolution.

Install

Iris is listed in the BB Community marketplace, so bb installs it by name. On a Mac running bb 0.48 or later:

bb plugin install iris

Or straight from this repository, following its release tags:

bb plugin install "git:https://github.com/vburojevic/bb-plugin-iris.git@^1.0.0"

That's it. New agent sessions learn Iris on their own, and the gallery appears in bb's sidebar under Iris. Sessions that were already running pick it up when they next start or resume. Iris adds about 3,600 tokens of instructions to each session it reaches: its rules and an index of every component. Prop details and examples load only when an agent asks for them.

Tip

Try every component in your browser first: the playground runs Iris's real renderer, with a live editor and links you can share.

Why Iris

Show, don't tell. Status reports, proof that work is done, PR and CI state, comparisons and plans come back as cards, with the answer in a sentence or two above them.

140 components. Layout, charts, data grids, diagrams, code and diffs, test and coverage reports, eval runs, agent traces, flame graphs, plans, decisions, maps, media, 3D, math, sheets, API inspectors, whiteboards and more. See every one.

Your theme, live. Colors come only from your bb theme: the accent is its primary, tones use its success, warning and danger colors, and nothing has a palette of its own.

Live data. A live card re-reads its files every 2 seconds. load("bb:...") reads bb itself, and any plugin can feed cards through a public data contract.

Interactive both ways. Inputs recompute cards in place, buttons put text in your composer, and iris_ask opens a rich picker that waits for your answer, like bb's own ask mode: ranked checklists with badges, design variants you flip through in a large preview, a color with its contrast, boxes and notes drawn on a screenshot, comments on a spec, or a list to put in order.

Apps when you need them. ```iris-react and ```iris-app run full React or HTML apps in a sandbox with no network, styled like native cards.

Safe by design. No eval: a sandboxed interpreter runs every expression under a step budget, cards make no network requests of their own, and web images load only when their URL is in the block. More

Measured. Every release passes an eval suite that runs real chat moments through an agent and scores whether it showed the right card. It scores 94.5 of 100 today, over 35 cases run twice each.

How it works

An agent writes JSX-style markup with live values, and bb renders it as you read.

<state seats={10} plan="Pro" />
<let price={(plan == "Pro" ? 29 : 12) * seats} />
<Card title="Estimate" icon="calculator">
  <Row>
    <Segmented bind="plan" options={["Basic", "Pro"]} />
    <Slider bind="seats" min={1} max={50} label="Seats" />
  </Row>
  <Row>
    <Metric label="Per month" value={price} format="usd" />
    <Metric label="Per year" value={price * 12 * 0.85}
            format="usd" note="15% off yearly" />
  </Row>
</Card>
The Estimate card: a plan toggle, a seats slider and two metrics that recompute as you move them That block, as bb draws it. Try it, and change it, in the playground.

From the agent's reply to a card you can use:

flowchart LR
  A["Agent writes<br>an iris block"] --> B["iris_check<br>reads its files, moves every<br>input, outlines the card"]
  B --> C["bb streams the reply;<br>each tag draws<br>as it arrives"]
  C --> D["You use the card:<br>inputs recompute,<br>live cards re-read every 2 s"]
  D -- "a button or a picker" --> E["Your answer goes<br>back to the agent"]
Loading

A broken part shows a readable error with an Ask to fix button while the rest of the card renders.

Components

The right card for the moment

Acceptance: Is it really done: each criterion with its status, a note and evidence that opens.
Proof it's done
Acceptance Is it really done: each criterion with its status, a note and evidence that opens.
Decision: Options scored against criteria with weights people can tune; the ranking updates live.
A decision to make
Decision Options scored against criteria with weights people can tune; the ranking updates live.
Chart: Line, area, bar, horizontal bar, pie, donut, scatter and radar charts in the theme's colors, with hover readouts, annotations and a table view.
Data to read
Chart Line, area, bar, horizontal bar, pie, donut, scatter and radar charts in the theme's colors, with hover readouts, annotations and a table view.
Tests: A test run: counts, failures first with messages and file links.
A test run
Tests A test run: counts, failures first with messages and file links.
PullRequest: This branch's pull request: state, checks, review status, mergeability and a link.
Where the PR stands
PullRequest This branch's pull request: state, checks, review status, mergeability and a link.
Plan: Steps of work with files, risk and estimates.
A plan to approve
Plan Steps of work with files, risk and estimates.
Forecast: Done counts over time as an ETA with a band from recent rates, a burn-down or burn-up, scope changes and plain words.
When it will land
Forecast Done counts over time as an ETA with a band from recent rates, a burn-down or burn-up, scope changes and plain words.
Budget: Spend against a limit: a meter per line, the total, a breakdown, the burn rate and when the limit is hit at it.
Spend against a limit
Budget Spend against a limit: a meter per line, the total, a breakdown, the burn rate and when the limit is hit at it.
CompareGrid: Many before and after image pairs in a grid, each tile with its changed-pixel count and a status (changed, missing, same); sort and filter by change.
What changed on screen
CompareGrid Many before and after image pairs in a grid, each tile with its changed-pixel count and a status (changed, missing, same); sort and filter by change.

Every component, by family

Open a family to see each card as it renders in bb. Every picture links to its live page in the playground, with its code and every prop.

Layout · 8 components: Card, Stack, Row, Grid, Tabs, Tab, Details, Divider
Card: The frame for one idea: a titled surface with a toolbar (expand, export, source).
Card
The frame for one idea: a titled surface with a toolbar (expand, export, source).
Stack: Children in a column with even spacing.
Stack
Children in a column with even spacing.
Row: Children side by side with equal widths; wraps on narrow screens.
Row
Children side by side with equal widths; wraps on narrow screens.
Grid: Tiles in a responsive grid.
Grid
Tiles in a responsive grid.
Tabs: Switch between Tab children.
Tabs
Switch between Tab children.
Tab: One page inside Tabs.
Tab
One page inside Tabs.
Details: A collapsible section for secondary detail.
Details
A collapsible section for secondary detail.
Divider: A hairline between sections, optionally labeled.
Divider
A hairline between sections, optionally labeled.
Content · 14 components: Text, Heading, Callout, Metric, Badge, Icon, KeyValue, List, Item, Link, Image, Progress, Gauge, Empty
Text: Markdown prose: bold, italics, `code`, links, lists.
Text
Markdown prose: bold, italics, `code`, links, lists.
Heading: A section heading inside a card.
Heading
A section heading inside a card.
Callout: A highlighted note: a warning, a tip, the bottom line.
Callout
A highlighted note: a warning, a tip, the bottom line.
Metric: One key number with a label, an optional change and a sparkline.
Metric
One key number with a label, an optional change and a sparkline.
Badge: A one to three word status chip.
Badge
A one to three word status chip.
Icon: A Lucide icon.
Icon
A Lucide icon.
KeyValue: Labeled fields: settings, metadata, a summary.
KeyValue
Labeled fields: settings, metadata, a summary.
List: Rows with a title, detail, icon, trailing value and an optional click action.
List
Rows with a title, detail, icon, trailing value and an optional click action.
Item: One row inside List.
Item
One row inside List.
Link: A link to a URL or a workspace file.
Link
A link to a URL or a workspace file.
Image: An image from the workspace, thread storage or an https URL.
Image
An image from the workspace, thread storage or an https URL.
Progress: A bar showing how far along something is.
Progress
A bar showing how far along something is.
Gauge: A dial for one value against a range.
Gauge
A dial for one value against a range.
Empty: What to show when there is nothing: an icon, a line and an optional action.
Empty
What to show when there is nothing: an icon, a line and an optional action.
Data · 7 components: Table, Json, SegmentedBar, Sparkline, Heatmap, CalendarHeatmap, DataGrid
Table: Rows and columns with sorting, search, paging and number formatting.
Table
Rows and columns with sorting, search, paging and number formatting.
Json: A collapsible JSON explorer for an object or a loaded file.
Json
A collapsible JSON explorer for an object or a loaded file.
SegmentedBar: Shares of one whole as a single bar with a legend.
SegmentedBar
Shares of one whole as a single bar with a legend.
Sparkline: A tiny trend line for inline use.
Sparkline
A tiny trend line for inline use.
Heatmap: A grid of rows by columns, each cell colored by its value: eval scores by case and run, failures by suite and day, latency by route and region.
Heatmap
A grid of rows by columns, each cell colored by its value: eval scores by case and run, failures by suite and day, latency by route and region.
CalendarHeatmap: Activity per day on a calendar grid, like a contributions graph.
CalendarHeatmap
Activity per day on a calendar grid, like a contributions graph.
DataGrid: An explorer for large results (CSV, JSON, SQL.
DataGrid
An explorer for large results (CSV, JSON, SQL.
Charts · 1 component: Chart
Chart: Line, area, bar, horizontal bar, pie, donut, scatter and radar charts in the theme's colors, with hover readouts, annotations and a table view.
Chart
Line, area, bar, horizontal bar, pie, donut, scatter and radar charts in the theme's colors, with hover readouts, annotations and a table view.
Diagrams · 3 components: Diagram, Tree, Graph
Diagram: A Mermaid diagram (flowchart, sequence, state, class, ER, gantt).
Diagram
A Mermaid diagram (flowchart, sequence, state, class, ER, gantt).
Tree: A collapsible tree: a file tree, a hierarchy, an outline.
Tree
A collapsible tree: a file tree, a hierarchy, an outline.
Graph: An interactive node-and-edge graph from data: dependency, call, module or service graphs.
Graph
An interactive node-and-edge graph from data: dependency, call, module or service graphs.
Code · 5 components: Code, Snippet, Diff, Logs, StackTrace
Code: A code block with syntax highlighting in bb's code theme.
Code
A code block with syntax highlighting in bb's code theme.
Snippet: Lines of a real file from the workspace, read when the card renders; clicking opens the file.
Snippet
Lines of a real file from the workspace, read when the card renders; clicking opens the file.
Diff: A unified diff for one file in bb's diff viewer, unified or split.
Diff
A unified diff for one file in bb's diff viewer, unified or split.
Logs: Command output with real ANSI colors, line numbers, a filter and error lines marked.
Logs
Command output with real ANSI colors, line numbers, a filter and error lines marked.
StackTrace: An error and its stack with your own frames highlighted and clickable; library frames fold away.
StackTrace
An error and its stack with your own frames highlighted and clickable; library frames fold away.
Project · 12 components: Tests, Findings, Coverage, Benchmark, Delta, TestHistory, Changes, Commits, PullRequest, Environments, Threads, Pipeline
Tests: A test run: counts, failures first with messages and file links.
Tests
A test run: counts, failures first with messages and file links.
Findings: Review, lint or type errors grouped by severity, each with file, line, detail and fix.
Findings
Review, lint or type errors grouped by severity, each with file, line, detail and fix.
Coverage: Code coverage per file with the weakest files first.
Coverage
Code coverage per file with the weakest files first.
Benchmark: Before and after timings with the change and whether it improved.
Benchmark
Before and after timings with the change and whether it improved.
Delta: Before and after for any values: each row's change, its percent and whether it went the right way, with a tally of better, worse and same.
Delta
Before and after for any values: each row's change, its percent and whether it went the right way, with a tally of better, worse and same.
TestHistory: Pass and fail per test across runs, with flaky tests (pass and fail flipping, or passing on retry) marked first, then failing ones and since when, then fixed ones.
TestHistory
Pass and fail per test across runs, with flaky tests (pass and fail flipping, or passing on retry) marked first, then failing ones and since when, then fixed ones.
Changes: Files changed in this thread's checkout with +/- counts; each expands to its diff.
Changes
Files changed in this thread's checkout with +/- counts; each expands to its diff.
Commits: This branch's commits since the default branch, newest first; each opens its changes.
Commits
This branch's commits since the default branch, newest first; each opens its changes.
PullRequest: This branch's pull request: state, checks, review status, mergeability and a link.
PullRequest
This branch's pull request: state, checks, review status, mergeability and a link.
Environments: This project's worktrees: branch, threads in each, changed file count and pull request.
Environments
This project's worktrees: branch, threads in each, changed file count and pull request.
Threads: Live status of bb threads: running, waiting on the person, done, failed.
Threads
Live status of bb threads: running, waiting on the person, done, failed.
Pipeline: A CI run: runs, jobs and steps with status and duration, failures open.
Pipeline
A CI run: runs, jobs and steps with status and duration, failures open.
Agents · 4 components: EvalReport, AgentTrace, ContextMeter, ToolCall
EvalReport: Eval cases across runs against a baseline: the score and its change, categories, and a case-by-run grid with regressions first.
EvalReport
Eval cases across runs against a baseline: the score and its change, categories, and a case-by-run grid with regressions first.
AgentTrace: An agent run as a span tree on a timeline: model calls, tool calls and subagents with time, tokens, cost and errors.
AgentTrace
An agent run as a span tree on a timeline: model calls, tool calls and subagents with time, tokens, cost and errors.
ContextMeter: How full a session's context window is, split by category, with model, cost and how both moved over the session.
ContextMeter
How full a session's context window is, split by category, with model, cost and how both moved over the session.
ToolCall: One tool or MCP call: name and server, arguments, result, timing and retries, collapsed to one line until opened.
ToolCall
One tool or MCP call: name and server, arguments, result, timing and retries, collapsed to one line until opened.
Debug · 3 components: Flamegraph, Bisect, BlastRadius
Flamegraph: A CPU profile as a flame graph: click a frame to zoom into it, search to highlight matches and their share, hover for self and total time, and the heaviest functions listed.
Flamegraph
A CPU profile as a flame graph: click a frame to zoom into it, search to highlight matches and their share, hover for self and total time, and the heaviest functions listed.
Bisect: A git bisect in flight: the commits from good to bad, each marked, the range still in play, the commit under test and about how many steps are left.
Bisect
A git bisect in flight: the commits from good to bad, each marked, the range still in play, the commit under test and about how many steps are left.
BlastRadius: What a change can break: each changed file with the files that import it, level by level, and the tests that reach it, as a tree.
BlastRadius
What a change can break: each changed file with the files that import it, level by level, and the tests that reach it, as a tree.
Evidence · 4 components: Acceptance, Compare, CompareGrid, Provenance
Acceptance: Is it really done: each criterion with its status, a note and evidence that opens.
Acceptance
Is it really done: each criterion with its status, a note and evidence that opens.
Compare: A visual difference between screenshots, reference first: wipe (a draggable divider), side by side, blink, or diff (changed pixels marked, with a count).
Compare
A visual difference between screenshots, reference first: wipe (a draggable divider), side by side, blink, or diff (changed pixels marked, with a count).
CompareGrid: Many before and after image pairs in a grid, each tile with its changed-pixel count and a status (changed, missing, same); sort and filter by change.
CompareGrid
Many before and after image pairs in a grid, each tile with its changed-pixel count and a status (changed, missing, same); sort and filter by change.
Provenance: Which build or revision is really installed or deployed where, from source to live, one stage per step.
Provenance
Which build or revision is really installed or deployed where, from source to live, one stage per step.
Planning · 10 components: Plan, Steps, Timeline, Decision, Board, Roadmap, Estimate, Calendar, Status, DecisionLog
Plan: Steps of work with files, risk and estimates.
Plan
Steps of work with files, risk and estimates.
Steps: A checklist of progress: done, current, todo, blocked.
Steps
A checklist of progress: done, current, todo, blocked.
Timeline: Dated events in order, newest or oldest first.
Timeline
Dated events in order, newest or oldest first.
Decision: Options scored against criteria with weights people can tune; the ranking updates live.
Decision
Options scored against criteria with weights people can tune; the ranking updates live.
Board: A kanban board: cards in status columns.
Board
A kanban board: cards in status columns.
Roadmap: A Gantt chart of dated work in lanes, with milestones and a today line.
Roadmap
A Gantt chart of dated work in lanes, with milestones and a today line.
Estimate: Three-point estimates with P50 and P90 totals.
Estimate
Three-point estimates with P50 and P90 totals.
Calendar: Events on a month grid.
Calendar
Events on a month grid.
Status: Health of several workstreams: on track, at risk, off track, done.
Status
Health of several workstreams: on track, at risk, off track, done.
DecisionLog: Decisions made so far: topic, what was decided, who decided, why and when, newest first, with topic filters and search.
DecisionLog
Decisions made so far: topic, what was decided, who decided, why and when, newest first, with topic filters and search.
Inputs · 14 components: Slider, Stepper, Toggle, Segmented, Select, Radio, Checklist, Rank, ColorInput, Input, TextArea, DateInput, Rating, Button
Slider: Pick a number on a range; the card recomputes live.
Slider
Pick a number on a range; the card recomputes live.
Stepper: A count with minus and plus buttons.
Stepper
A count with minus and plus buttons.
Toggle: An on/off switch.
Toggle
An on/off switch.
Segmented: Pick one of a few short options.
Segmented
Pick one of a few short options.
Select: Pick one of many options from a menu.
Select
Pick one of many options from a menu.
Radio: Pick one option, each with a detail line.
Radio
Pick one option, each with a detail line.
Checklist: Pick several options; the state is a list of the picked values.
Checklist
Pick several options; the state is a list of the picked values.
Rank: The person puts options in order: drag the grip, or the up and down buttons, or Alt and the arrow keys.
Rank
The person puts options in order: drag the grip, or the up and down buttons, or Alt and the arrow keys.
ColorInput: Pick a color: a swatch that opens the system picker, a hex field, optional presets, and the contrast on each background it will sit on.
ColorInput
Pick a color: a swatch that opens the system picker, a hex field, optional presets, and the contrast on each background it will sit on.
Input: A one-line text field.
Input
A one-line text field.
TextArea: A multi-line text field.
TextArea
A multi-line text field.
DateInput: Pick a date (yyyy-mm-dd).
DateInput
Pick a date (yyyy-mm-dd).
Rating: One to N stars.
Rating
One to N stars.
Button: Runs an action: change state, put text in the composer, send it, copy, open a file or URL.
Button
Runs an action: change state, put text in the composer, send it, copy, open a file or URL.
Pickers · 5 components: FollowUps, Choices, Submit, Variants, Variant
FollowUps: Suggested next prompts after a finished answer.
FollowUps
Suggested next prompts after a finished answer.
Choices: Optional next steps after a finished turn as tappable cards; the pick goes into the composer.
Choices
Optional next steps after a finished turn as tappable cards; the pick goes into the composer.
Submit: Only inside an iris_ask picker: sends the answer back to you.
Submit
Only inside an iris_ask picker: sends the answer back to you.
Variants: Design directions to flip through: one large preview at a time with a switcher, arrows and keys.
Variants
Design directions to flip through: one large preview at a time with a switcher, arrows and keys.
Variant: One direction inside Variants: its preview is its children, or html for a sandboxed mock page.
Variant
One direction inside Variants: its preview is its children, or html for a sandboxed mock page.
Media · 8 components: Gallery, Screens, Hotspots, Map, PhotoSearch, VideoPlayer, VideoCompare, AudioPlayer
Gallery: Images in a grid; a click opens a lightbox with arrows, Esc to close and the caption.
Gallery
Images in a grid; a click opens a lightbox with arrows, Esc to close and the caption.
Screens: Screenshots as a matrix: one row per screen, one column per device, theme or locale, each tile with its label and an optional status.
Screens
Screenshots as a matrix: one row per screen, one column per device, theme or locale, each tile with its label and an optional status.
Hotspots: Numbered pins on an image; each opens its title and text.
Hotspots
Numbered pins on an image; each opens its title and text.
Map: Places on an OpenStreetMap map with a numbered list beside it, fit to show them all; route joins them in order with distances.
Map
Places on an OpenStreetMap map with a numbered list beside it, fit to show them all; route joins them in order with distances.
PhotoSearch: A real photo for a description, from Wikimedia Commons only, with its author and license credited under it.
PhotoSearch
A real photo for a description, from Wikimedia Commons only, with its author and license credited under it.
VideoPlayer: A video that streams and seeks: chapters on the scrubber and in a list, notes that jump to their time, frame stepping (, and .
VideoPlayer
A video that streams and seeks: chapters on the scrubber and in a list, notes that jump to their time, frame stepping (, and .
VideoCompare: Two videos on one timeline, reference first: one play and scrub control, side by side or wipe, frame steps (, and .), speed, and an offset that aligns them ([ and ] shift a frame).
VideoCompare
Two videos on one timeline, reference first: one play and scrub control, side by side or wipe, frame steps (, and .), speed, and an offset that aligns them ([ and ] shift a frame).
AudioPlayer: Audio with a waveform drawn from the decoded file (click or drag to seek) and a transcript whose current line highlights and follows.
AudioPlayer
Audio with a waveform drawn from the decoded file (click or drag to seek) and a transcript whose current line highlights and follows.
Design · 6 components: DeviceFrame, Swatches, TypeSpecimen, MarkUp, Annotate, ThemePreview
DeviceFrame: A screenshot inside a phone, tablet, Mac window or browser frame, drawn plainly with no brand artwork.
DeviceFrame
A screenshot inside a phone, tablet, Mac window or browser frame, drawn plainly with no brand artwork.
Swatches: Colors with names and their WCAG contrast ratio against each background you choose, marked pass or fail for AA and AAA, normal and large text.
Swatches
Colors with names and their WCAG contrast ratio against each background you choose, marked pass or fail for AA and AAA, normal and large text.
TypeSpecimen: A font rendered at each size and weight with sample text, for checking a type scale.
TypeSpecimen
A font rendered at each size and weight with sample text, for checking a type scale.
MarkUp: The person marks up an image: boxes, arrows and pins, each numbered with a note.
MarkUp
The person marks up an image: boxes, arrows and pins, each numbered with a note.
Annotate: A screenshot with numbered callouts: boxes drawn over regions, or pins, given in percent.
Annotate
A screenshot with numbered callouts: boxes drawn over regions, or pins, given in percent.
ThemePreview: A mock app screen drawn only from the theme you give it (primary, background, foreground, border, radius, font and more), following inputs live: bind ColorInput and Slider states to it to try a theme.
ThemePreview
A mock app screen drawn only from the theme you give it (primary, background, foreground, border, radius, font and more), following inputs live: bind ColorInput and Slider states to it to try a theme.
Math · 2 components: Math, FunctionPlot
Math: TeX formulas typeset with KaTeX.
Math
TeX formulas typeset with KaTeX.
FunctionPlot: Plots y = f(x) for one or more arrow functions over a domain, with a hover readout.
FunctionPlot
Plots y = f(x) for one or more arrow functions over a domain, with a hover readout.
Live · 2 components: LiveLog, LiveProgress
LiveLog: Tails a log file a running job keeps writing: ANSI colors, error lines marked, scrolls with new output and pauses when you scroll up.
LiveLog
Tails a log file a running job keeps writing: ANSI colors, error lines marked, scrolls with new output and pauses when you scroll up.
LiveProgress: Progress of a running job read from a JSON file it rewrites: {done, total, label?, eta?} or {tasks: [...]}.
LiveProgress
Progress of a running job read from a JSON file it rewrites: {done, total, label?, eta?} or {tasks: [...]}.
Learning · 4 components: Quiz, Flashcards, Walkthrough, Timer
Quiz: Questions one at a time with options; each answer shows right or wrong and why.
Quiz
Questions one at a time with options; each answer shows right or wrong and why.
Flashcards: A deck to practice: click or Space flips a card, then sort it into Know it or Still learning (keys K and L, or the arrows).
Flashcards
A deck to practice: click or Space flips a card, then sort it into Know it or Still learning (keys K and L, or the arrows).
Walkthrough: A guided explanation one step at a time: a title, markdown and optional code with highlighted lines.
Walkthrough
A guided explanation one step at a time: a title, markdown and optional code with highlighted lines.
Timer: A countdown (give seconds) or a stopwatch with laps.
Timer
A countdown (give seconds) or a stopwatch with laps.
Graphics · 2 components: Scene, Shader
Scene: A 3D scene in three.js the person can orbit (drag), zoom (scroll or pinch) and click.
Scene
A 3D scene in three.js the person can orbit (drag), zoom (scroll or pinch) and click.
Shader: A Shadertoy-style fragment shader in WebGL2: write mainImage(out vec4 fragColor, in vec2 fragCoord) with iTime, iResolution, iMouse, iFrame, iTimeDelta, iDate, plus theme colors iPalette[0..3], iBackground, iForeground.
Shader
A Shadertoy-style fragment shader in WebGL2: write mainImage(out vec4 fragColor, in vec2 fragCoord) with iTime, iResolution, iMouse, iFrame, iTimeDelta, iDate, plus theme colors iPalette[0..3], iBackground, iForeground.
Sheets · 1 component: Sheet
Sheet: An editable spreadsheet.
Sheet
An editable spreadsheet.
API · 5 components: HttpExchange, Waterfall, ErDiagram, QueryPlan, SchemaDiff
HttpExchange: One HTTP request and its response: method, URL, status, time, size, headers (secrets masked) and the body as a JSON tree or text.
HttpExchange
One HTTP request and its response: method, URL, status, time, size, headers (secrets masked) and the body as a JSON tree or text.
Waterfall: Network requests on a timeline: each bar split into queue, DNS, connect, TLS, wait and download, with DOMContentLoaded and Load lines.
Waterfall
Network requests on a timeline: each bar split into queue, DNS, connect, TLS, wait and download, with DOMContentLoaded and Load lines.
ErDiagram: Tables, columns and relations drawn from schema text: SQL CREATE TABLE, a Prisma schema or a Convex schema.ts (format is detected).
ErDiagram
Tables, columns and relations drawn from schema text: SQL CREATE TABLE, a Prisma schema or a Convex schema.ts (format is detected).
QueryPlan: A Postgres EXPLAIN (FORMAT JSON) plan as a collapsible tree: each node's own time (with ANALYZE) or cost as a bar, estimated against actual rows, and warnings for bad estimates, spills and big filtered scans.
QueryPlan
A Postgres EXPLAIN (FORMAT JSON) plan as a collapsible tree: each node's own time (with ANALYZE) or cost as a bar, estimated against actual rows, and warnings for bad estimates, spills and big filtered scans.
SchemaDiff: A database migration before it runs: each table with columns added, changed or dropped, every step marked destructive (loses data), risky (can fail, lock or break running code) or safe.
SchemaDiff
A database migration before it runs: each table with columns added, changed or dropped, every step marked destructive (loses data), risky (can fail, lock or break running code) or safe.
Review · 3 components: CodeTour, DocReview, Redline
CodeTour: A guided walk across real files: each step highlights lines in a workspace file with a markdown note.
CodeTour
A guided walk across real files: each step highlights lines in a workspace file with a markdown note.
DocReview: A spec, plan or doc (markdown) the person reads and comments on, block by block, then approves or asks for changes.
DocReview
A spec, plan or doc (markdown) the person reads and comments on, block by block, then approves or asks for changes.
Redline: A word-level redline of prose (docs, copy, specs): deletions struck, insertions marked inline.
Redline
A word-level redline of prose (docs, copy, specs): deletions struck, insertions marked inline.
Terminal · 2 components: TerminalReplay, DevServers
TerminalReplay: Replays a recorded terminal session with its timing and real ANSI colors: play, pause, speed, scrub and markers.
TerminalReplay
Replays a recorded terminal session with its timing and real ANSI colors: play, pause, speed, scrub and markers.
DevServers: Live list of running dev servers and their ports: status, port links, pid, CPU, memory, uptime and log.
DevServers
Live list of running dev servers and their ports: status, port links, pid, CPU, memory, uptime and log.
Whiteboard · 1 component: Whiteboard
Whiteboard: A freeform canvas of sticky notes, groups, text and arrows.
Whiteboard
A freeform canvas of sticky notes, groups, text and arrows.
Localization · 1 component: StringsTable
StringsTable: Localized strings side by side: a row per key, a column per locale, each cell flagged when missing, untranslated, marked for review, with placeholders that don't match the source, or likely to truncate.
StringsTable
Localized strings side by side: a row per key, a column per locale, each cell flagged when missing, untranslated, marked for review, with placeholders that don't match the source, or likely to truncate.
Files · 4 components: FileTree, AssetGallery, PdfViewer, FontPreview
FileTree: A real folder from the workspace or thread storage as a tree: file and folder sizes, git markers (A M D R U) from this checkout's changes, a filter and a Changed only toggle.
FileTree
A real folder from the workspace or thread storage as a tree: file and folder sizes, git markers (A M D R U) from this checkout's changes, a filter and a Changed only toggle.
AssetGallery: Every image, SVG and app icon under a folder, grouped by kind, each with its pixel size and file size on a checkerboard.
AssetGallery
Every image, SVG and app icon under a folder, grouped by kind, each with its pixel size and file size on a checkerboard.
PdfViewer: A PDF rendered page by page with pdf.js (pages draw as they scroll in): page count and jump, zoom, fit width.
PdfViewer
A PDF rendered page by page with pdf.js (pages draw as they scroll in): page count and jump, zoom, fit width.
FontPreview: A font file (ttf, otf, woff, woff2) loaded as is: its names, format and metrics, editable sample text at any size, sliders for variable axes, and a grid of every glyph it maps.
FontPreview
A font file (ttf, otf, woff, woff2) loaded as is: its names, format and metrics, editable sample text at any size, sliders for variable axes, and a grid of every glyph it maps.
Compute · 1 component: Cells
Cells: A notebook-like stack of named cells run by Iris's sandboxed interpreter, each showing its value (number, text, list, table or component).
Cells
A notebook-like stack of named cells run by Iris's sandboxed interpreter, each showing its value (number, text, list, table or component).
Time · 3 components: TimeZones, Cron, DateDiff
TimeZones: A meeting planner across time zones: rows of people or places on a shared 24-hour scale, working hours shaded, and a slot the person drags (or moves with arrow keys) showing each local time.
TimeZones
A meeting planner across time zones: rows of people or places on a shared 24-hour scale, working hours shaded, and a slot the person drags (or moves with arrow keys) showing each local time.
Cron: A cron schedule read as plain words, each field explained, and the next runs listed with how far away they are.
Cron
A cron schedule read as plain words, each field explained, and the next runs listed with how far away they are.
DateDiff: Business days between two dates: working days, calendar days, weeks, weekends and the holidays skipped, over a day strip of the range.
DateDiff
Business days between two dates: working days, calendar days, weeks, weekends and the holidays skipped, over a day strip of the range.
Release · 1 component: Release
Release: One card for a release: version, build, overall state, platforms, checks, store or TestFlight state, blockers and a timeline.
Release
One card for a release: version, build, overall state, platforms, checks, store or TestFlight state, blockers and a timeline.
Accessibility · 1 component: AccessibilityAudit
AccessibilityAudit: An axe-core or Lighthouse accessibility report: counts by impact, failing rules grouped by impact or WCAG criterion, each with its nodes (selector, HTML, how it fails) and help link.
AccessibilityAudit
An axe-core or Lighthouse accessibility report: counts by impact, failing rules grouped by impact or WCAG criterion, each with its nodes (selector, HTML, how it fails) and help link.
Geo · 1 component: GeoHeatmap
GeoHeatmap: A choropleth of countries or US states shaded by value in one accent hue, with a legend, hover readouts and a table view.
GeoHeatmap
A choropleth of countries or US states shaded by value in one accent hue, with a legend, hover readouts and a table view.
Tracking · 2 components: Budget, Forecast
Budget: Spend against a limit: a meter per line, the total, a breakdown, the burn rate and when the limit is hit at it.
Budget
Spend against a limit: a meter per line, the total, a breakdown, the burn rate and when the limit is hit at it.
Forecast: Done counts over time as an ETA with a band from recent rates, a burn-down or burn-up, scope changes and plain words.
Forecast
Done counts over time as an ETA with a band from recent rates, a burn-down or burn-up, scope changes and plain words.

Live data from bb itself

Changes: files changed in this thread's checkout with line counts, each opening its diff
Changes This thread's changed files, each opening its diff.
Threads: live status of the threads this thread started
Threads The threads it started: running, waiting on you, done or failed.

Cards read bb's own live data with load("bb:<source>"), scoped to the card's thread (its project and the threads it started), and draw it with any component. Inside <Card state="live"> it re-reads every 2 seconds; iris_check reads the real values, so the agent sees what the card will. The live project components, <Changes>, <Commits>, <PullRequest>, <Threads> and <Environments>, read bb themselves and update as soon as bb reports a change.

<let t={load("bb:thread")} />
<let kids={load("bb:threads?usage=1")} />
<Card title="This session" state="live">
  <Gauge label="Context" value={t.context ? t.context.percent : 0} format="percent" />
  <Table rows={kids} columns={["title", "status", {key: "waitingOnYou", label: "Needs you"}]} />
</Card>

<ContextMeter thread={load("bb:thread")} /> draws the context window split by category, with model and cost; in a live card it keeps the readings it sees as a history line, where compactions show as drops. Given load("bb:threads?usage=1") it totals context and cost by model.

Every bb: source
Source What it returns
bb:thread This thread: title, status, waiting on you, queued messages, context window use (tokens, percent, model, categories), cost
bb:threads Threads this thread started; ?scope=project for the project's top-level threads; ?usage=1 adds context and cost
bb:usage Plan usage windows per provider: used percent, resets at, spend and limit
bb:pr This branch's pull request: state, checks, review, mergeability
bb:commits This branch's commits since its base, ahead and behind
bb:changes Files changed on this branch, uncommitted included, with line counts
bb:environments The project's worktrees with their threads, changed files and pull requests
bb:machines bb machines and whether they're connected
bb:plugins Installed plugins and their health
bb:terminals This thread's terminals: title, status, exit code; ?output=1 adds the tail of what each prints, for a live <Logs>

Live cards that ride out a slow answer

A live card keeps showing its last good values when a refresh fails, with a quiet "Last updated 14:02 · retrying" under it, and shows an error only for a source that never read fine. load(path, {fallback: value}) gives the card a value of its own to show instead of an error. Plugin data (plugin: sources) refreshes every 10 seconds rather than every 2, and cards on the page share one read of the same source.

Pin a card beside the conversation

Hover any card in a thread and press the pin button: the card stays in view while the chat scrolls on, still live. A thread keeps up to five pins, each marked with who pinned it and with its own Unpin, and pins follow the thread to your other devices. They show in four places:

  • Above the composer, as a "2 pinned" chip. A click opens the pinned cards right there; on a phone this is the quickest way to them.
  • On bb's home page, under Pinned cards: every open thread's pins, live, the most recently pinned first. A thread's title opens it.
  • In the thread context card at the pane's upper right, when that is on in bb (Settings, Experiments, Thread context card). The chip hides itself there.
  • In the thread's right panel (Info tab, under Pinned cards).

The thread's agent can pin too, for a status it keeps current:

  • iris_pin pins a card from its source, or from a file such as $BB_THREAD_STORAGE/status.iris. A file pin re-reads the file every 3 seconds, so the agent updates the card by rewriting the file. The card is checked first; one with errors isn't pinned. Pinning again with the same id replaces the pin in place.
  • iris_unpin and iris_pins remove and list the thread's pins.
  • From a shell: bb iris pin <file> [--id fleet] [--title ...] [--once] [--alert-when ...] [--alert-message ...], bb iris unpin <id>|--all and bb iris pins [--json]. These act on the thread they run in only.
  • Any client can use the same pins through bb plugin rpc call iris pins.list|pins.all|pins.set|pins.ack|pins.remove (listed by bb plugin rpc list iris).

Pins that alert you

A pin can carry a condition over its card's own names, for example iris_pin with alert_when: 'build.state == "failed"' on a card that loads build from a status file. Iris checks it every 30 seconds, reading the card's files and feeds as the card would. When it turns true:

  • the pin shows the alert with Dismiss, and the chip above the composer reads "2 pinned · 1 alert";
  • every open bb window shows a toast with Open (bb keeps it in its notification center);
  • bb's desktop app shows a system notification when bb may already show them and its window isn't in front;
  • the thread is marked unread, so it stands out in the sidebar on every device.

It asks again only after the condition clears and holds again. A source that is still loading or can't be read leaves the alert as it was. Alerts never message the thread or wake the agent.

Phone pushes aren't possible: bb gives plugins no notification API, and bb's push notifications fire only when an agent finishes a turn or asks a question. On the phone, an alert shows as the thread's unread mark and on the pin itself.

Copy a card as an image

Every card's toolbar, and every pin, has Copy as image: the card is drawn to a PNG in your theme, without its toolbar, and put on the clipboard. Where a page can't write images to the clipboard (some browsers, the phone app), the PNG is saved instead: a download on a computer, the share sheet on a phone. Pages and apps (iris-app and iris-react blocks) run in a sandboxed frame the page can't read, so they don't copy as images.

A card that lives in a file

An agent can keep a card in a file and show it inline: it writes the markup to $BB_THREAD_STORAGE/status.iris and puts ::iris{file="$BB_THREAD_STORAGE/status.iris"} on its own line in a reply. The card follows the file, read again every 3 seconds while it is on screen, so rewriting the file updates the card in place. A failed read keeps the last good card with a note. The same file can be pinned with iris_pin to keep it in view.

Read back what the person set, and set it

iris_cards (or bb iris cards [--json], or the cards.list RPC) lists the thread's cards, newest last, with what the person set in each: a slider's value, a pick, typed notes, stored values. An agent can act on a card's state without asking again.

iris_card_set sets those inputs instead: {card: "<id>", values: {seats: 20}} with the card's id from iris_cards (or its number), bb iris set <id> seats=20, or the cards.set RPC. Each value must be a <state> the card declares and keep its type; the card is checked with the new values first, and an open card redraws with them at once. The agent can show the person another scenario in the card they already have.

Checks that read the real data

iris_check and bb iris check read the card's files, bb data and plugin feeds (plugin: sources, up to 5 seconds each) the way the card will, and warn when a required prop comes out empty, naming the fields the data does have (<Metric value> is empty: it has no field "ship"; its fields are ships, status).

They also warn when a Table or Gallery holds data a more specific component draws better, with the rewrite built from the card's own columns: before and after values point at Delta, checks with results at Acceptance, severity and file at Findings, colors at Swatches or Variants, screenshots captioned by device or theme at Screens, and before and after shots at Compare (<Table> reads as before and after (case, before, after): <Delta rows={rows.map((r) => ({ label: r.case, before: r.before, after: r.after }))} />). Warnings never block a card.

Ask for a card, or take one to the browser

  • Show as an Iris card. In a message's menu, this asks the agent to redo that answer as a card. Select part of a message first to ask about just that part. The composer has the same command.
  • Open in the web playground. A card's toolbar opens it in the playground, ready to edit and share. The card's source travels after the # in the link, so no server sees it. Files and bb data the card loads stay on your Mac, so they show as pending there.
  • Iris: open the playground in bb's command palette opens an empty editor.

For plugin authors: live data in Iris cards

Any bb plugin can feed live data to Iris cards without Iris knowing about it. Serve read-only JSON (or CSV) under the /iris/ prefix of your plugin's HTTP routes:

bb.http.route("GET", "/iris/status", (c) => Response.json(statusFor(c.req.query("thread"))), { auth: "local" });

Cards then read it with load("plugin:<your-plugin-id>/status"). Check a feed the way a card reads it with bb iris feed check <your-plugin-id>/status: whether it answers, its content type, size and time, caching, and the fields a card can use. Iris fetches /api/v1/plugins/<id>/http/iris/status?thread=<threadId> from bb's own page, parses it by content type, and re-reads it every 2 seconds inside a <Card state="live">. Only the /iris/ prefix is ever read, answers are capped at 4 MB, and query keys pass through (plugin:notes/today?tag=work). Teach your plugin's agents to draw it with a line in your own instructions; Iris needs no change. Iris serves a sample at plugin:iris/example.

Important

Treat everything under /iris/ as readable by any card in any thread. The thread parameter is a hint for scoping, not access control, so publish only what any agent may show. Cards can't send it to a place of their choosing: they make no network requests of their own, and a web image or media file loads only when its full URL is written in the block. With webLookups on, a map's places and a photo's search words do go to OpenStreetMap, Photon and Wikimedia Commons through Iris's server, so don't feed private data into those. A card choosing among several written URLs can still signal which one it picked, so don't publish secrets.

For agents

Agents get these tools, and the same checks run from a shell. iris_examples(["Recipes"]) returns patterns that combine them: a status card that follows a file, a Variants picker, and setting a card's inputs.

Agent tools
Tool What it does
iris_check Validates a block, reads its files, moves every input to its extremes, and returns an outline of what the person will see; an iris-react module is compiled and its imports checked
iris_docs Every prop and an example for the named components
iris_examples Working examples for whole component families, and recipes (["Recipes"])
iris_ask A waiting picker written in Iris markup, an iris-react app or HTML; the answer comes back as JSON
iris_pin, iris_unpin, iris_pins Pin a card (or a file holding one) beside the conversation, unpin, list
iris_cards, iris_card_set Read what the person set in the thread's cards, and set a card's inputs
CLI
Command What it does
bb iris check <file> Checks a block or iris-react app from a file and prints what the person will see
bb iris components Lists every component with its one-line summary
bb iris docs <Name> Every prop and an example for the named components
bb iris try "<prompt>" Runs a prompt in a subthread that knows Iris
bb iris pin <file>, bb iris unpin <id>, bb iris pins Pin, unpin and list this thread's pinned cards
bb iris cards, bb iris set <n> name=value List this thread's cards with their inputs, and set a card's inputs
bb iris feed check <plugin>/<name> Checks a plugin's Iris data feed the way a card reads it

Settings

Iris reaches every top-level thread, whoever started it, and leaves threads that agents spawn under them alone unless you turn workers on.

Every setting
Setting Values Default
stance eager shows anything that can be shown; balanced keeps short answers as prose eager
rollout everywhere (every top-level thread), or trial for threads started with bb iris try only everywhere
workers Teach threads that agents spawn under a top-level thread too (about 3,600 tokens of instructions per session) false
skipPlugins Plugin ids, comma-separated, whose own top-level threads skip Iris empty
webLookups Maps, place search and photos through Iris's server (OpenStreetMap, Photon, Wikimedia Commons) true

Change one with bb plugin config iris set <key> <value>, then bb plugin reload iris.

Security

  • Expressions run in a tree-walking interpreter: no eval, no globals, no prototype access, and a step budget per evaluation. Only functions Iris registers can be called.
  • load(), <Snippet> and <Image> read only the thread's workspace and thread storage (and other threads' storage folders), through the plugin's server, up to 8 MB. Players, PDFs and fonts stream through a bb preview lease scoped to that same root, which bb checks on every request and which expires after an hour.
  • Cards make no network requests of their own. With webLookups on (the default), Iris's server looks up map places and tiles (OpenStreetMap, Photon) and photos (Wikimedia Commons) for <Map> and <PhotoSearch>, so the place names and search words written in those cards reach those services. Turn webLookups off to keep every card offline.
  • ```iris-app pages and ```iris-react apps run in a sandboxed iframe with an opaque origin and a no-network content policy injected before any of their markup. Sending a message never happens from the page alone: Iris shows the exact text in a bar outside the frame, and only a click on its Send button sends it. A picker answer goes back at once only right after a click inside the page; any other answer waits in that bar. Insert, copy and open a link act only right after a click inside the page.

Note

Known limit: a sandboxed page can still navigate itself, so it could send away data it already holds. It never holds anything the agent didn't put in the block.

Evals

npm run eval runs 35 generic chat moments (status reports, mid-task progress updates, proof that something is done, PR and CI state, data to decide on, rich questions for the person, cards kept in view) through Claude Code headless with exactly the instructions and tools Iris gives agents in bb (iris_docs, iris_examples, iris_check, and stand-ins for iris_ask and iris_pin that log their calls, served by evals/mcp-server.ts). Each answer is scored on Iris being used (a block, a ::iris{file} card, or a picker or pin), every card checking clean, a fitting component and tool, and no markdown tables, plus a 1 to 5 judgment of fit. Every case runs twice and scores the mean, so one unlucky answer moves the suite less. npm run release:check runs the tests, the type check, the site build and the eval gate, which fails when the score drops more than 3 points below evals/baseline.json and names the cases that fell most.

Develop

Build, test and record from a checkout
npm install
npm test                          # engine, catalog, reports, prompt size
npx tsc --noEmit
node scripts/build-chunks.mjs     # when a chunk changes; commit dist/chunks/
node scripts/brand.mjs            # regenerates the icon and logos
bb plugin install . && bb plugin dev

Develop against the one installed Iris: install the checkout once (bb plugin install .) and run bb plugin dev, which rebuilds and reloads on every save. Don't install extra copies under other ids.

The playground is the real gallery with bb's SDK swapped for a stand-in (site/). node scripts/build-site.mjs builds it into site-dist/; scripts/capture-site-css.mjs refreshes bb's CSS from a running bb, scripts/capture-atlas.mjs re-shoots the component pictures from the built site, npx tsx scripts/readme-atlas.ts rewrites the atlas above, node scripts/readme-icons.mjs redraws the feature icons, and scripts/record-demo.mjs with scripts/encode-demo.sh re-records the demo frame by frame from a separate dev bb.

License

Apache-2.0


Iris
Made for bb by Vedran Burojević. Open the playground.

About

Iris: live, interactive UI in bb chat. Agents draw charts, tables, plans, diffs, test runs, pickers and small apps in your theme.

Topics

Resources

Stars

5 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages