Kin / How Kin works

The Graphite+ identity

Understand Kin’s colors, disclosure, responsive layout, and motion controls.

Read as Markdown

The design language behind the kin interface: a terminal-owned ground with quiet Graphite+ structure and a cool, colourful reading palette. This page explains quiet disclosure and the palette behind it.

Cyan voice, neutral disclosure

Kin’s cyan role bar marks its voice. Cyan-blue headings, blue emphasis, lavender code and sage markers give its prose colour; reasoning stays neutral. Routine tools and delivered reasoning share shallow collapsed activity groups. Grey titles follow the current work and shimmer while that activity is live. They settle into quiet outcome summaries when it finishes. Structural rails keep detail available. File-edit diffs and bounded terminal excerpts sit outside the fold; routine failures retain a quiet marker without opening it.

Fenced code uses syntax highlighting with familiar editor cues. Code and prose share the reading palette while retaining distinct structure.

The markdown body

Headings use cyan-blue, emphasis soft blue, inline code lavender, and quotes and markers sage. Weight, spacing, and marks preserve structure without color. The composer uses the same heading and marker colors.

Routine tool calls and reasoning fold into shallow groups. Expand a group, then a row, for detail; file diffs and bounded terminal excerpts remain visible outside the fold. Search and copy retain delivered content behind previews.

The welcome

The welcome introduces Kin with a compact rendering of the shared Kinra K, the live product name and version, the model, and the workspace. A divider separates trust posture and release highlights when the terminal is wide enough. The emblem uses ordinary terminal cells, so it remains visible in remote sessions. Its blue gradient comes from the shared brand mark.

Hover and copy retain the complete identity, including the session id. A tip appears in the timeline each launch; release highlights appear in the welcome once after an update. Small panes retain the supplied trust posture. KIN_MARK=0 hides the emblem; KIN_ASCII hides it and uses a plain frame.

Terminal sizes

Messages reflow with the terminal, and the composer grows within a height budget. The Git header shows repository state. Below the composer, the session line shows model, effort, workspace, and context usage; hover or /tokens reveals details omitted at narrow widths. Context numerator and denominator stay together or are omitted together.

Short panes preserve input and reachable controls. Model, MCP, and search panels move details below their lists; dialogs and completion menus scroll. Use keybindings for disclosure and navigation.

The palette

Colours are named by role, not by hue, so a re-tint is a one-place edit. The role names below are the constants defined in theme.py.

Role Hue Hex Used for
GROUND graphite #101114 Opaque fallback, code bands, and lifted structure
FG bone #E3E3E6 Body text and the welcome’s product name
HEADING cyan-blue #80B8D0 Markdown and draft headings
HEADING_MINOR deeper blue-cyan #6FA1B8 Deeper Markdown headings
EMPHASIS soft blue #9DBADB Strong text and table headers
INLINE_CODE lavender #B7A5D3 Backticked symbols and composer literals
QUOTE soft sage #A0B49C Quoted prose and list/quote markers
PRIMARY cyan #5FBFD6 Kin’s role bar, the spinner, and interactive cues
PRIMARY_MUTED muted cyan #4B8FA2 The session line’s model and effort — Kin’s identity at rest, never a live cue
REASON periwinkle #9E97D2 Code syntax and the retained theme accent, not reasoning chrome
SECONDARY muted sage #859781 The session line’s workspace and human shell cue
SUCCESS green #5FC198 A tool succeeded
WARNING amber #D6A855 Warnings — distinct enough from cyan that the two never read alike
ERROR coral #E5786E Errors and failures
CODE_STRING muted green #83B692 String literals inside fenced code
RULE deep graphite #2A2E36 Rules and the low-contrast scrollbar thumb

These constants are the single place the palette is named. The Textual theme wires them into the UI’s CSS tokens, and the transcript widgets import the same constants directly for Rich text styles (Rich cannot read a CSS variable) — so a styled CSS rule and a hand-built renderable always land on the same colour.

Terminal ground

The default kin theme does not paint the main canvas. It inherits your terminal’s own background, including translucency, while keeping Graphite+ truecolour accents and intentional opaque surfaces such as code bands, diff washes, menus, and modal cards. This is a hybrid theme, not a retreat to the terminal’s ANSI palette: cyan still means live voice, reasoning is neutral, status colours keep their roles, and the composer cursor remains an opaque cyan block so the insertion point stays clear on the inherited ground.

The current contract is dark terminals. If your terminal palette is light, or you need a deterministic opaque canvas, run /theme kin-graphite. /theme cycles between the transparent kin theme and that opaque fallback; the choice is saved for future sessions. Any registered Textual theme can still be chosen by name as an explicit escape hatch. Cursor and search-result tints follow that selected theme’s primary colour; only transparent kin uses fixed Graphite+ preblends, because Textual cannot alpha-blend those cues against a terminal-owned background.

Measured palette contrast

The recessive greys and the shimmer base are tuned for WCAG against the opaque GROUND reference (#101114), not chosen by eye — the ratios are measured with the standard relative-luminance formula and live in theme.py next to each constant. Body-text grey (GREY_LO, reasoning tails / diff metadata / pygments comments) clears AA body at 4.65:1; the shimmer base (PRIMARY_DIM, the dim live-signal colour) clears AA Large at 3.21:1 while keeping a ~5.7-point delta below PRIMARY so the sweep stays visible. The new reading colours also clear AA body against the opaque ground, code band and panel. A terminal-owned background can change those measured ratios; use the kin-graphite fallback when guaranteed palette contrast matters.

Glyph vocabulary

theme.py owns shared disclosure, connector, status, and spinner glyphs. Widgets import those constants so the interface keeps one visual vocabulary.

Spinner vibes

Choose /spinner or set spinner / KIN_SPINNER. Unknown names use the default; KIN_ASCII forces the ASCII-safe line style.

name vibe frames cadence
rain (default) matrix ⠁⡄ ⠋⡄ ⠏⡀ ⠟⡈ … — drips falling down two braille cells, each drop randomly skipping beats and varying its tail (120 deterministic pre-baked frames, seamless ~9.6s loop) 0.08s
braille classic ⠋ ⠙ ⠹ ⠸ ⠼ ⠴ ⠦ ⠧ ⠇ ⠏ 0.10s
arc orbital ◜ ◠ ◝ ◞ ◡ ◟ 0.12s
toggle metronome ⊶ ⊷ 0.35s
line plain `- \ /`

Activity titles show observed work and elapsed time, then settle to an outcome. A completed activity does not imply the whole task succeeded. Hidden and completed titles stop animating.

Set TEXTUAL_ANIMATIONS=none to hold spinner frames, shimmers, and pulses still. A live activity title’s clock still advances once per second. Settled activity stays quiet in either mode.

Why calm

Color supports content and interactive cues; routine activity and borders remain quiet.