How Herdr for Android looks and why. It wears the Herdr desktop's workbench layout, an
engineering-puzzle-game console, carried over to a phone, and it is laid out as Shepherdr 3.1's
phone web app: a drawer of spaces, a bottom bar of Chat, Tasks and Artifacts.
Everything below lives in code in two places, and screens use nothing else:
ui/theme/Theme.kt: colours (Herdr.colors, the Material scheme), type (Sans,Mono,CodeStyle,caps()), spacing (Space), corners (Radius, all square), frames (Frame), the terminal's colours.ui/design/: the components (Components.kt,Chat.kt,NavBar.kt), the workbench's own pieces (Workbench.kt: glyphs, chip icons,Led,SlotNumber,CircuitBackdrop, from the generatedWorkbenchArt.kt), the icon set (HerdrIcons.kt) andAgentMark.
A screen that needs a number, a colour or a shape that isn't there adds it here first.
The look is the Herdr desktop's workbench layout (personal-herdr-desktop, Apache 2.0): its theme
(herdr-app/themes/workbench.json), its chip-package icons, dot-matrix glyphs, HERDR chip and
circuit board, which tools/workbench-art/gen.py turns into Compose vectors. The faces are Geist and
Geist Mono (SIL OFL 1.1). Icons the workbench has no glyph for are Lucide (ISC). Notices:
THIRD_PARTY_NOTICES.md.
Near-black panels, amber frames, status lights. Flat and minimal: frames and flat fills only.
- Flat. No gradients, glows, shadows or decorative fills. What floats (a sheet, a dialog, a toast) is framed, not lifted. Corners are square everywhere.
- Frames, 1dp. A module (a card, a group of rows, a tile) is a 1dp frame in
lineStrongon the ground. What is in focus or shown is framed in amber: a focused field, a dialog, a sheet's top edge, the chosen chip, the drawer's shown slot. - Amber is the console's. It marks focus, what is shown (the chosen tab, the shown space), your own action (Send, the primary button, the +), links, the cursor, and work: as on the desktop, working is amber. The other states have their own colours.
- Module headings in capitals. Sections, sheets, top-level titles, the nav's labels, the drawer's buses and slots are Geist Mono in capitals, tracked; a section heading runs a 1dp rule to the edge. What is read at length (prose, row titles, body) stays in sentence case in Geist.
- One status, shown once. A task or an agent says its state once: a square LED with its word, or the section it sits in, or its button (Accept), never two of them. Colour is never alone.
- No module inside a module. A card holds rows and sections, never another card.
- Bottom bar: Chat (the shown space), Tasks (owns the Needs you count, the only badge), Artifacts (the shown space's; where its machine has no Shepherdr, the machine's herdr.doc docs). Each a glyph over its name in mono capitals; the chosen one amber, with a 2dp amber bar along its top edge.
- Drawer of spaces (
ui/spaces/Spaces.kt), the desktop workbench's sidebar: the brand row (the HERDR chip, HERDR, an amber-framed WORKBENCH tag, search), SPACES, then each machine as a numbered bus (BUS 1 · DEVBOX, its meter: thin bars for CPU, memory and its tightest plan, amber near a limit and red past it; its connection LED; why, when it doesn't answer; a tap opens the machine) with its spaces as numbered slots (SlotNumber, the name in sentence case, the program's chip only where an agent really is, its one LED; the shown one onselectedwith an amber bar at its start and its number on amber). Classic herdr's and herdr-core's workspaces of one name are one slot. At its foot, Settings and Add machine. The circuit board shows, quietly, below the last bus. - Chat tab: the shown space's Assistant (Shepherdr), else its agent (the one that needs you first), else its terminals. The bar's leading button opens the drawer; its layers glyph opens the space's menu: its tabs (each agent's chat and terminal, each shell), New task, Assistant, Start an agent, and its machine.
- Tasks tab (3.1's Tasks list): a Filter tasks field and a filter row (All, then each group with its count), then Pinned, Needs you (one row each, its answer beside it), Ready (with Accept), Working, Queued, To do, Done (five, then Show N more), Idle. One row per task: a task's agent is its row. A + offers New task, Assistant and Start an agent.
- Wide (840dp and more): the drawer stays open on the left as a sidebar; the app fills the rest.
Dark is the workbench theme value for value (ContrastTest.darkIsTheWorkbenchTheme); light is its
counterpart on paper, with dark-amber frames, made in the same language.
Token (Herdr.colors) |
Workbench | Dark | Light | Use |
|---|---|---|---|---|
ground |
background |
#0D0F10 |
#F1EEE6 |
Screens, the chat canvas, the terminal |
panel |
chrome |
#0A0D0C |
#ECE8DE |
Bars, the nav bar, the drawer, sheets, dialogs, toasts |
card |
surface |
#1B1F21 |
#FBFAF6 |
Your chat turns, tiles, tracks |
hover |
hover (a step darker) |
#252B2E |
#E4E0D4 |
Pressed rows, keys |
selected |
selected |
#1E3A40 |
#D9E6E3 |
The shown space, the chosen action |
input |
input |
#090A0B |
#FFFFFF |
Text fields |
line |
#283033 |
#D5CFC0 |
Rules between rows, a section heading's rule | |
lineStrong |
border |
#4E5B57 |
#8E897C |
Module frames, keycaps, an off switch |
frame |
amber at half | #7A5809 |
#B98A3A |
A quiet amber frame |
text |
foreground |
#DFE4E1 |
#1E2224 |
Body and row text |
strong |
#F4F6F5 |
#0B0D0E |
Titles, emphasis | |
muted |
muted |
#8FA3A8 |
#4F5B60 |
Secondary lines, icons, headings, meta |
off |
dim |
#66727A |
#9AA2A3 |
Disabled, a resting LED, chip pins (not text) |
accent |
accent |
#FFB000 |
#7A4C00 |
Amber that reads as text and frames focus |
primary / onPrimary |
accent / accent_foreground |
#FFB000 / #0B0D0E |
#FFB000 / #0B0D0E |
The fill of your own action, with ink |
teal |
ansi6 |
#4FD1C5 |
#0E7A70 |
The runtimes' chip ink |
notice |
ansi11 |
#FFCC4D |
#6E5600 |
Offline, stale, near a limit |
scrim |
#050606 60% |
#281F16 35% |
Under sheets, dialogs, the drawer |
| State | Workbench | Dark | Light | Agent | Task |
|---|---|---|---|---|---|
| Working | working |
#FFB000 |
#7A4C00 |
working | working, merging |
| Blocked | blocked |
#FF5A4A |
#A3211A |
needs you | needs you |
| Done | done |
#5FD38A |
#17623A |
done | ready, done |
| Idle | idle |
#8FA3A8 (as text) |
#4F5B60 |
idle, other | queued, to do |
A state shows as an Led (a 6–7dp square) with its word (StatusBadge: the LED and the word in
mono capitals in the state's colour, flat), or as the section it sits in. Red is also the colour of
destructive actions. Code takes its own syntax colours (HerdrColors.syntax(role)); the terminal
the workbench's sixteen ANSI colours, any cell held at 4.5:1 on its background.
Geist Mono (Mono) is the console's voice: titles, headings, labels, buttons, chips, the nav,
code, paths, keys and the terminal. Geist (Sans) is for reading: prose, row titles, body.
Both bundled (res/font, Regular, Medium, SemiBold). In sp, so they follow the phone's font size:
| Style | Size / line | Face | Use |
|---|---|---|---|
headlineMedium |
18 / 23.4, +0.04em | Mono SemiBold, capitals | Top-level titles (TASKS) |
headlineSmall |
18 / 23.4 | Sans SemiBold | A task's title, Markdown h1 |
titleLarge |
15 / 20.3 | Mono SemiBold | Detail bars, sheets, dialogs, empty states (capitals) |
titleMedium |
14 / 21 | Sans Medium | Row and card titles |
titleSmall |
12 / 16.8, +0.08em | Mono SemiBold, capitals | Section headings, tiles |
bodyLarge |
15 / 24 | Sans | Chat prose, your turns, menu rows |
bodyMedium |
14 / 21 | Sans | Body and dialog copy |
bodySmall |
12 / 18 | Sans | Subtitles, hints, meta |
labelLarge |
13 / 18.2 | Mono Medium | Buttons, chips, segments, slots |
labelMedium |
12 / 16.2 | Mono Medium | Counts, pills |
labelSmall |
11 / 14.3, +0.08em | Mono SemiBold, capitals | Badges, field labels, nav labels, buses |
CodeStyle |
13 / 20 | Mono | Code, the terminal (its own size) |
Capitals are written with caps(); what a screen reader hears keeps the words as written.
Space: a 4dp grid, xs 4, s 8, m 12, l 16, xl 20, xxl 24, xxxl 32. Screen margin 16,
module padding 12. Radius: every one is 0. Frame: 1dp. Targets at least 48dp; bars 56dp; rows
48–56dp; icons 20dp; chip icons 20–22dp; LEDs 6–7dp.
- Dot-matrix glyphs (
GlyphArt, the desktop's px-chromegwset) wherever the workbench draws one: search, settings, plus, minus, X, check, chevrons, server, monitor, terminal, folder, files, branch, pull request, compare, pin, archive, clock, layers, the sidebar.HerdrIconsreturns them under Lucide's names, so screens don't change. - Lucide (
HerdrIcons) for the rest, at its own geometry (24-unit grid, 2-unit strokes).IconsTestkeeps every icon one or the other. - Chip-package icons (
ChipIcon,chipFor(program),AgentMark) for programs and agents, as the desktop marks them: Claude, Codex, a generic agent chip for the other agents; shell, git, vim, nvim, make, htop, ssh in the tools' grey; bun, node, npm, python, go, cargo, docker in the runtimes' teal; agents in amber. The body is a step off the ground, the pinsoff. No brand logos.
CircuitBackdrop draws the desktop's backgrounds/workbench.svg covering its box, in colours a
step off the ground. It shows only where there is room to spare: behind empty states and under the
drawer's last bus. Never under rows of text; text over an empty state sits on the ground.
| Surface | Fill | Edge |
|---|---|---|
| Screen | ground |
|
| Top bar, nav bar, bottom action bar | panel |
a lineStrong rule on the content side |
Module (QuietCard) |
none (the ground) | lineStrong frame; chosen: selected with an amber frame |
Sheet (HerdrSheet, HerdrMenu) |
panel |
an amber top edge, a short lineStrong handle |
Dialog (HerdrDialog) |
panel |
amber frame |
| Drawer | panel |
lineStrong rule at its edge |
| Toast | panel |
amber frame (red for an error) |
| Composer, prompt card | card |
lineStrong; the prompt card red, amber while typing |
+ (HerdrFab) |
primary |
square |
| Code block, terminal | panel / ground |
| Component | Anatomy |
|---|---|
HerdrTopBar |
panel, a strong rule under it. Top level: the drawer's button, the title in mono capitals, actions. Detail: back arrow, title in mono, the place under it dim. A screen shown as a tab (the Chat tab) opens the drawer instead of going back, and the tab adds its own action after the screen's (LocalBarDrawer, LocalInTab, LocalBarMore). |
HerdrNavBar / NavItem |
See Layout. |
SectionHeading |
Mono capitals in muted (or a state's colour when it needs you), then a 1dp line rule to the edge or to its trailing action. |
QuietCard |
A module: a lineStrong frame, flat. Holds rows and sections. |
Needs you rows (WaitingRow) |
One row per item: the agent's chip, the title, its key and space, the question in two lines, and its one action beside it (Accept, Give it, Answer; a yes/no keeps both answers as square buttons, the main one amber). No status badge: the section says it. The full card stays in the task's chat. |
ListRow, ActionRow, MenuRow |
Optional leading cell, title, a dim line, trailing or chevron. A chosen action row sits on selected with a 3dp amber bar at its start. |
PrimaryButton / SecondaryButton / QuietButton / DangerButton |
Square, 48dp, mono labels: amber with ink / framed on the ground / bare / the danger tint framed in red. |
HerdrChip |
A framed cell; chosen: amber frame, amber text on amber's tint. |
SegmentedPills |
One framed track; the chosen segment amber with ink. |
ViewTabs |
The views of one thing (a task's Chat, Files, Changes, Pull request, Browser) under its bar: on panel over a lineStrong rule, names in mono capitals, the shown one amber with a 2dp amber bar along its bottom edge; scrolls sideways when they don't fit. |
HerdrField |
Label in mono capitals, the box on input framed in lineStrong, amber while focused. |
HerdrSwitch, SwitchRow |
Square: a framed track with a square knob; on, amber with an ink knob. |
StatusBadge, StatusLabel, Led |
See States. |
SlotNumber |
The desktop's space index cell: "01" in mono, framed; amber with ink when shown. |
IconTile |
A square framed tile; a status LED cut into its corner. |
ChatComposer, chat |
As before in behaviour (one round of controls, Send, Stop, mic, attach, held messages, the prompt card docked over it); square and flat, framed in lineStrong, amber while typing. Placeholder: "Message " everywhere, "Message the Assistant" for an Assistant. A turn at work shows one working line. |
| Prompt card | Framed in red (the chat's status line says it needs you); its action tag on the right; its choices as square buttons. |
| Terminal | ground, text, amber cursor, the workbench's ANSI colours; keys framed, an armed modifier amber. |
- Empty (
EmptyState): over the circuit board, a square framed tile with a dim glyph, the title in mono capitals, one dim sentence, the button that fixes it when there is one. - Loading (
LoadingState,Spinner): a thin dim spinner with square ends, a dim line. Before any machine answers, the Tasks tab says Connecting to N machines…, not an error. - Error:
ErrorMessage(danger tint, red frame, one sentence, Retry);ErrorStatefull-area. - Offline: a
notice"Offline · showing the last known state" over the stale content.
Short and quiet: navigation fades and slides (200ms); sheets rise; dialogs fade (150ms); toasts drop in from the top; the nav's amber bar cross-fades (180ms). A working agent's dot breathes; nothing else moves on its own.
- Every target is at least 48dp (terminal keys 52×48).
- Text 4.5:1 and marks 3:1 in both themes, on every surface text sits on and on the state tints
(
ContrastTest); the amber focus frame 3:1 on the ground. - Layouts hold at 200% font scale; all type is in sp.
- Words in capitals are drawn so; screen readers get them as written (
contentDescription). - Icon-only buttons have content descriptions; rows that open something say what; headings are headings; states are words, not only colours.
- Nothing is only behind a long press: a card or row with a long-press sheet offers its actions as TalkBack custom actions on itself.
- Back is predictive (
BackHandlers, neveronBackPressed). - Chats and the terminal have their own text sizes (Settings → Text size).