Kin / How Kin works
The Graphite+ identity
Understand Kin’s colors, disclosure, responsive layout, and motion controls.
Read as MarkdownThe 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.