README.md

code-browser is a browser for reading code: you move through repos, reviews and agent runs the way you move through the web, and you review what changed — and who changed it — the way you would in an editor. The system is a quiet instrument: warm graphite neutrals, one signal accent, mono where the machine speaks, hairlines instead of shadows. The code and the diff carry the colour; the chrome stays out of the way.

Principles #

  1. The diff is the interface. Add and delete colours, word emphasis and the review state are the loudest things on screen. Chrome never competes with them.
  2. Declared generation is visible. Content whose author declared it generated carries the agent hue or a generated tag. Authors are never coloured or tagged by what kind of author they are. Never infer generation, and never imply a person wrote something because it lacks the mark.
  3. One signal. signal means "here" (focus, caret, selection, the ref you are on) or "look at this" (flagged, medium risk, the one primary action). Never decoration.
  4. Everything has an address. Every view has an omnibar URL; every review action has a key.
  5. Say where code runs. Nothing from a browsed repo runs on the host. Anything that executed — a language server's answer, test output, a build — says which sandbox it ran in, and the boundary is one click away.
  6. Dense but calm. 13px text on 20px lines, 4px grid, hairline dividers. Density comes from rhythm, not from cramming.

Sandboxes #

  • One review is one trust domain is one VM. Name the domain as repo @ref sha wherever a sandbox is shown.
  • Show where code runs with SandboxBadge in the chrome, and put the details in SandboxCard. There is no "host" state to design for; "no sandbox" is normal and means nothing has executed.
  • Boundary words are fixed: none, read-only, throwaway, limited, open. Only open takes colour (signal). Always pair a word with the concrete detail (no NIC · host proxy · :80 :443).
  • Workload and sandbox states reuse one glyph set: ○ none or pending · ◌ starting or building (signal) · ◐ indexing · ● ready (add dot) · ◉ running · ✕ failed (del) · ⊘ unavailable.
  • Blocked egress is shown, never hidden: a ✕ N count on the badge, and every attempt in EgressLog with the proxy's reason. Only an allow-list miss gets a one-click "Allow host".
  • Output from the sandbox (ExecOutput) marks each line's stream with a gutter glyph and starts with a meta line restating the boundary.

Voice and content #

  • Sentence case everywhere. Only micro (badges, eyebrows) is set in capitals.
  • Verb first, name the object: "Approve change set", "Revert hunk", "Ask agent". Never "OK", "Submit", "Done".
  • Plain and specific, second person when addressing the reviewer: "You haven't viewed 3 files."
  • Report facts, not feelings: "5 files · +110 −76 · medium risk", not "Looks good!". No emoji in the UI.
  • Code identifiers, paths, refs, run ids and counts are set in mono (code, code-sm); prose around them stays sans.
  • Every author's text follows the same voice rules, whoever wrote it.
  • The generated tag reads "Generated", optionally followed by the declared model in code-sm mono: "Generated · claude-opus-5-5".

Colour #

Dark is the primary theme; light mirrors it token for token.

  • Grounds: bg-000 is the canvas behind code; bg-100 the chrome (tabs, omnibar row, sidebars); bg-200 raised surfaces (cards, popovers, hunk headers); bg-300 hover and current line.
  • Lines: line for hairline dividers (decorative only); line-strong for control borders, which must meet 3:1.
  • Text: ink for primary text and all code; ink-muted for paths, metadata, line numbers; ink-faint for timestamps and placeholders, only on bg-000–bg-200.
  • Signal: signal for focus (focus), caret, the current ref, selection edges, the flagged state and the single primary button (on-signal text). signal-soft fills selected rows and ranges (selection).
  • Provenance: agent on agent-soft for generated content only: generated tags, generated comment grounds, and the 3px agent tick in the gutter on lines that a declared-generated entry quotes or proposes.
  • Diff: add-bg / del-bg for line grounds, add-emph / del-emph for changed words, add / del for the +/− signs, counts and the approved / changes-requested states. Code on any diff ground stays ink.
  • Status mapping: approved → add, changes requested → del, flagged → signal, generated → agent; info → neutrals; viewed and unreviewed → neutrals.
  • Never by hue alone. add and del are close in lightness, so every diff line draws its + / − sign, every file row its status letter (A M D R), every review state its glyph (○ ◐ ✓ ✕ !), every provenance tag the word "Generated". Keep it that way in anything new.
  • Every text pair named in a token's usage note holds 4.5:1 in both themes; line-strong, focus and signal hold 3:1 on bg-000–bg-200.

Type #

  • Instrument Sans (--font-sans) for interface text; JetBrains Mono (--font-mono) for code and everything the machine produces. Both ship with the system as variable WOFF2 files in fonts/ (Instrument Sans upright and italic, weights 400–700; JetBrains Mono upright, 100–800), declared by tokens.css. The UI uses 400, 500 and 600. Both are under the SIL Open Font License 1.1; the license texts sit beside the files and must travel with them.
  • Interface: title 20/28 once per view (the review, run or file); heading 15/20 for panels and cards; body 13/20 default; label 12/16 for buttons, tabs, tree rows; micro 11/14 caps for badges.
  • Code: code 13/20 in diffs and files — its 20px line is row-code, so code and gutters stay on one rhythm; code-sm 12/16 for line numbers, hunk headers, refs, paths, stats and keycaps.
  • display (mono 40/44) is reserved for the product name and empty-state headlines.
  • File names in trees and tabs are mono; prose titles are sans.

Space, size and layout #

  • 4px grid: space-1 4 · space-2 8 · space-3 12 · space-4 16 · space-6 24 · space-8 32 · space-12 48.
  • Fixed rows keep the instrument steady: row-code 20, row-tree 26, control-sm 22, control-md 28, chrome-h 40, gutter-w 44 per line-number column.
  • Layout: the omnibar row on top, on the macOS traffic-light line, then the tab strip below it, only while tabs are open and without the product mark (bg-100, chrome-h each); file tree left; the diff or file on the bg-000 canvas centre; activity and review panel right. Panes are separated by line, never by gaps or shadows.
  • Pad cards and panels with space-4; separate sections inside a pane with space-6.

Shape, borders and elevation #

  • Corners: radius-xs (2) for word marks, stat blocks, keycaps; radius-sm (4) for buttons, inputs, badges, tags, tabs; radius-md (6) for cards, hunks, popovers, the omnibar field. radius-pill is for status dots only.
  • Docked things are flat and bordered with line. Only floating layers (omnibar suggestions, menus, command palette, toasts) take shadow-pop.
  • No gradients, no coloured card edges, no glows.

States and focus #

  • Hover: one step up the ground scale (bg-100 → bg-200 → bg-300).
  • Selected: signal-soft fill; in lists add a 2px signal edge.
  • Focus: 2px solid focus ring with 1px offset on every interactive element, shown on keyboard focus (:focus-visible).
  • Disabled: 45% opacity, no hover.
  • Keys: every primary action has one. A button names its key in its hover tip, never as a keycap in the button; Kbd keycaps are for menus, key lists and chrome.
  • Active tab: joins the canvas (bg-000) with a 2px signal top edge.

Motion #

  • Short and functional: 120ms ease-out for hover and selection, 160ms for popovers and toasts opening. Nothing bounces.
  • Scrolling to the next hunk is instant or a 160ms ease; never animate code text.
  • Any long-running task shows a static ◆ in ink-muted unless its progress is known, never a spinner.

Iconography #

  • No icon set is part of the system yet. Components use typographic glyphs instead: + − for diff signs, ○ ◐ ✓ ✕ ! for review states, A M D R for file status, ◆ for in progress / working, › ⌄ for disclosure, ← → for back and forward, × for closing a tab (never the ✕ failure state).
  • Review threads have their own sets, chosen not to collide with the review states: thread kinds ¶ note · ? question · ▲ issue · ± suggestion · ✦ praise; thread status □ open · ▣ resolved · ⊟ won't fix · ⬚ outdated; review lifecycle ✎ draft · ↑ submitted · ⇢ superseded · ⤺ withdrawn; verdicts ✓ approved · ✕ changes requested · “ comment · – no verdict (the first two reuse the review-state glyphs because they mean the same thing).
  • Issue severity is read by word and weight, not hue: only blocker takes colour (signal). del stays reserved for changes requested and failures.
  • When icons are added, use a 1.5px-stroke outline set at 16px, drawn in ink-muted and taking ink on hover; never colour an icon unless it carries a state colour defined above.

The mark is [▮]: a pair of square brackets holding a block caret. The brackets are code — the thing being read; the caret is the reviewer's place in it, in signal. It reads as "you are here, inside the code", which is what code-browser is for.

  • Construction (64-unit grid): bracket stems and arms 6 units thick, 48 tall, arms 16 long; the caret 10 × 26, centred. 8 units of clear space are built into the square; keep at least that much again around it.
  • Colour: brackets in ink, caret in signal, using the file made for the ground — -on-dark on bg-000–bg-200 in the dark theme, -on-light in the light theme. Use the mono marks only where one ink is required (embossing, single-colour print, stamps): mark-mono-ink on light grounds, mark-mono-paper on dark.
  • Lockup: the mark followed by the wordmark, separated by one character cell, the name's cap height centred on the mark. Use it where the product is introduced (sign-in, about, docs header); use the mark alone in app chrome, where the name is already known.
  • Wordmark: code-browser outlined from JetBrains Mono Medium — lowercase, hyphenated, never split, capitalised or retyped in another face.
  • Small sizes: the mark holds down to 24px. Below that use favicon (drawn on a 16px pixel grid, on its own bg-100 tile). app-icon-dark is the default app icon; app-icon-light is for light OS surfaces.
  • Don't: recolour the brackets, put the caret in any colour but signal (or the mono ink), animate the caret blinking in static placements, outline or add shadows, set the mark on signal or on busy imagery.

Maintaining this system #

This artifact is published output. The source is the design-system/ folder of the code-browser repository, which mirrors this system's project/ folder file for file. Every publish from the repo replaces what's here, so an edit made directly to this artifact (on its page or by publishing files to it) is overwritten by the next one. Make changes in the repo instead: edit, run bun run ds:build, commit, then publish with the repo's push-design-system skill.

The components' source is components/src/ (one typed React module per component, props in types.ts); never edit components/bundle.js or components/index.d.ts, which components/build.mjs builds from it and type-checks. bun run ds:build also recompiles tokens.css from tokens.json and refreshes the Components and Logos tables at the end of this README. These hand-kept parts exist because the design system format's own generation (tokens.css, the README's generated index, manifest.json, api/ cards, and building the bundle from source) doesn't run for systems edited from Claude; if those files ever appear on their own, the hand-kept parts can go.

Consuming this system #

Namespace: CodeBrowser — components/bundle.js assigns window.CodeBrowser, one export per component in the table below. Libraries: React 18 and ReactDOM 18 (not bundled; a Design canvas supplies its own React 18). Stylesheets: components/bundle.css, which expects tokens.css loaded first. Fonts: Instrument Sans and JetBrains Mono, as files under fonts/, declared with @font-face at the top of tokens.css (relative url("fonts/…"), so keep fonts/ next to tokens.css). Nothing loads from the network.

Every path below is a file in this system; read it by path.

  • In an app build (the Electron renderer): import from components/src/index.ts directly — it's plain TypeScript React whose only dependencies are react and react-dom (18 or 19; Dialog portals with createPortal), and it type-checks under strict with noUncheckedIndexedAccess — and load bundle.css after tokens.css. The code-browser app does this from the same repository, so it needs no copy.
  • No project/api/ cards. This system has no generated per-component cards and no manifest.json. Before using a component, read its project/components/<Name>/README.md (guidelines, what the consumer provides) and its entry in project/components/index.d.ts (props and value shapes); its preview.html is a working example.
  • Installing on a Design canvas: copy components/bundle.js, components/bundle.css, components/index.d.ts, tokens.json, tokens.css and the three fonts/*.woff2 files (all served under project/), keeping fonts/ beside tokens.css. Link ds/<folder>/tokens.css before bundle.css in each artboard. Mount components as <x-import component-from-global-scope="CodeBrowser.<Name>" …>. No provider component is needed.
  • Logos are uploads in this system, not files: a canvas can't reach them by this system's asset ids. Read the logo you need by id (table below), upload it to the canvas, and pass the canvas's own /_blob/… URLs (for example to Tabs' mark).

Files #

path what
project/tokens.json All tokens: colour (themes dark, light), type, spacing, radius, shadow, size. Every token has a usage note.
project/tokens.css The same tokens compiled to CSS: @font-face for the font files, custom properties per theme, and a class per type style. Load it first.
project/fonts/InstrumentSans-Variable.woff2 · InstrumentSans-Italic-Variable.woff2 · JetBrainsMono-Variable.woff2 The font files (variable WOFF2), listed in tokens.json type.fonts. Referenced from tokens.css by relative URL.
project/fonts/InstrumentSans-OFL.txt · JetBrainsMono-OFL.txt SIL Open Font License 1.1 for each family. Ship them with the fonts.
project/components/src/*.tsx The source. One typed React module per component (<Name>.tsx), shared helpers in internal.tsx, prop types in types.ts, everything exported from index.ts. Edit these, never bundle.js. Imports only each other, react and react-dom.
project/components/build.mjs Builds bundle.js and index.d.ts from src/: node build.mjs <path to components> with esbuild, typescript@5, @types/react@19, @types/react-dom@19 and dts-bundle-generator installed. Type-checks first under strict and noUncheckedIndexedAccess (the same strictness the app builds with), so a type error fails the build.
project/components/bundle.js Built from src/ — don't edit by hand. One classic script. Needs window.React and window.ReactDOM 18 loaded first; assigns window.CodeBrowser with every component below.
project/components/bundle.css Component styles. Load after the token CSS.
project/components/index.d.ts Generated from src/: every component's props type (<Name>Props) and signature.
project/components/<Name>/README.md Guidelines per component: what it is, rules, what the consumer provides.
project/components/<Name>/preview.html A live example per component (expects tokens, bundle.css, React and bundle.js preloaded).
project/assets/Logos/README.md Which logo file to use where, and the inks baked into each.

Tokens as CSS #

Load project/tokens.css. It starts with one @font-face per file in fonts/, then defines every token as --<name>: colours and shadows per theme under :root, [data-theme="dark"] and [data-theme="light"] (aliases such as focus are var(--signal)), spacing, radius and size on :root, the families as --font-sans and --font-mono, and one class per type style (.title, .body, .code, …). Set data-theme="dark" or "light" on <html>. The type classes are deliberately global and unprefixed: they are the format's compiled shape for type styles, and they're the only selectors in the system outside cb-. Nothing in bundle.css depends on them, so a consumer can ignore them, but it shouldn't define its own .title, .heading, .body, .label, .micro, .code, .code-sm or .display with a different meaning. It is compiled from tokens.json; if they ever disagree, tokens.json wins.

Load order: tokens.css → bundle.css → React 18 → ReactDOM 18 → bundle.js. Then const { Button } = window.CodeBrowser.

Components #

component group summary files
Button Actions Buttons commit a review decision or run a command; default is the workhorse and primary (signal fill) appears at most once per view, for the decision the view exists to make. project/components/Button/README.md · project/components/Button/preview.html
Kbd Actions A keyboard hint. project/components/Kbd/README.md · project/components/Kbd/preview.html
Switch Forms An on/off toggle for boolean settings. project/components/Switch/README.md · project/components/Switch/preview.html
Segmented Forms Two to four mutually exclusive options shown at once. project/components/Segmented/README.md · project/components/Segmented/preview.html
Select Forms A styled native select for five or more options, or where the options come from data (remotes, branches, themes). project/components/Select/README.md · project/components/Select/preview.html
TextField Forms A single-line input. project/components/TextField/README.md · project/components/TextField/preview.html
TextArea Forms The multi-line version of TextField, for review summaries, comments and replies. project/components/TextArea/README.md · project/components/TextArea/preview.html
Omnibar Chrome The address bar. project/components/Omnibar/README.md · project/components/Omnibar/preview.html
Tabs Chrome The browser tab strip, sized chrome-h; each tab says what kind of thing it holds (review, reviews, file, run, web) in a mono prefix. project/components/Tabs/README.md · project/components/Tabs/preview.html
NavButtons Chrome Back and forward through the view history, like a browser's. project/components/NavButtons/README.md · project/components/NavButtons/preview.html
FileTree Navigation The changed-files tree. project/components/FileTree/README.md · project/components/FileTree/preview.html
DiffHunk Review One unified-diff hunk. project/components/DiffHunk/README.md · project/components/DiffHunk/preview.html
DiffStat Review The size of a change. project/components/DiffStat/README.md · project/components/DiffStat/preview.html
ReviewBadge Review The review state of a file, hunk, tab or change set — the core vocabulary of code-browser. project/components/ReviewBadge/README.md · project/components/ReviewBadge/preview.html
ChangeSetCard Review The summary of one change set waiting for review. project/components/ChangeSetCard/README.md · project/components/ChangeSetCard/preview.html
ReviewLifecycleBadge Review A review's own state, as opposed to the state of what it reviews (that's ReviewBadge). project/components/ReviewLifecycleBadge/README.md · project/components/ReviewLifecycleBadge/preview.html
VerdictBadge Review A review's verdict, in the review format's own values. project/components/VerdictBadge/README.md · project/components/VerdictBadge/preview.html
ReviewListItem Review One review in a reviews list (a repository's reviews, the "waiting on you" inbox, earlier rounds of a re-review). project/components/ReviewListItem/README.md · project/components/ReviewListItem/preview.html
ThreadKindTag Review threads What kind of thread this is, and for issues how severe. project/components/ThreadKindTag/README.md · project/components/ThreadKindTag/preview.html
ThreadStatus Review threads Where a thread stands. project/components/ThreadStatus/README.md · project/components/ThreadStatus/preview.html
Thread Review threads One code thread. project/components/Thread/README.md · project/components/Thread/preview.html
ThreadListItem Review threads One row in a review panel's thread list. project/components/ThreadListItem/README.md · project/components/ThreadListItem/preview.html
CoverageSummary Review threads How much of the change the reviewer has actually looked at. project/components/CoverageSummary/README.md · project/components/CoverageSummary/preview.html
AuthorTag Authorship Who wrote it. project/components/AuthorTag/README.md · project/components/AuthorTag/preview.html
GeneratedTag Authorship Marks content whose author declared it generated. project/components/GeneratedTag/README.md · project/components/GeneratedTag/preview.html
CodePeek Code intelligence A floating card that answers "what is this?" for one symbol without leaving the diff. project/components/CodePeek/README.md · project/components/CodePeek/preview.html
ReferencesCard Code intelligence Every occurrence of a symbol, grouped by file, framed around the reviewer's real question. project/components/ReferencesCard/README.md · project/components/ReferencesCard/preview.html
CallHierarchy Code intelligence Callers and callees of one function as a collapsible tree — the change's blast radius. project/components/CallHierarchy/README.md · project/components/CallHierarchy/preview.html
TypeHierarchy Code intelligence Supertypes and subtypes of a class or interface. project/components/TypeHierarchy/README.md · project/components/TypeHierarchy/preview.html
SandboxBadge Sandbox The chrome indicator for where code from the current review runs. project/components/SandboxBadge/README.md · project/components/SandboxBadge/preview.html
SandboxCard Sandbox The sandbox for one review, in one card. project/components/SandboxCard/README.md · project/components/SandboxCard/preview.html
EgressLog Sandbox Every connection attempt from the sandbox, allowed or blocked, as the host-side proxy decided it. project/components/EgressLog/README.md · project/components/EgressLog/preview.html
ExecOutput Sandbox The streamed output of one command run in the sandbox. project/components/ExecOutput/README.md · project/components/ExecOutput/preview.html
Notice Feedback An inline banner for something the reviewer should know about the current view. project/components/Notice/README.md · project/components/Notice/preview.html
Dialog Feedback A floating panel for a decision that needs the reviewer's full attention. project/components/Dialog/README.md · project/components/Dialog/preview.html
LossReport Feedback The body for export and conversion previews. project/components/LossReport/README.md · project/components/LossReport/preview.html
Toast Feedback A brief message about something that just happened. project/components/Toast/README.md · project/components/Toast/preview.html
SettingsPage Pages The settings editor. project/components/SettingsPage/README.md · project/components/SettingsPage/preview.html

Logos #

Uploads in the Logos group, read by asset id. Guidance in project/assets/Logos/README.md.

file asset id
mark-on-dark.svg caa94715df22b5760138a96a37f11296
mark-on-light.svg a135a80931c6f5580bac1d2d985610c5
lockup-on-dark.svg c27a0453568446bdf9bf7d8de7898074
lockup-on-light.svg f0bbafa61a1783e89796371c8cd5f701
wordmark-on-dark.svg 36fd42842e9e559139358dc8997a6d68
wordmark-on-light.svg 61b97255d408e75856bea064c5e48e9d
mark-mono-ink.svg f0f30efe3f5bee39c03862e7ef84fce1
mark-mono-paper.svg b3ba2d4537f7482cbcad983d66366d2c
app-icon-dark.svg c3d40fc5766fe77a5540a9d3a38de24d
app-icon-light.svg e64e63e76524ba072668464d1ea22dd7
favicon.svg efdff4ac2329e4b8a3d1e4d70c4f4360