| 1 | # Accessibility |
| 2 | |
| 3 | DeepSeek-TUI runs in a terminal, so the platform's own accessibility |
| 4 | stack (screen readers, magnifiers, terminal-level themes) does most |
| 5 | of the work. The TUI provides a small set of toggles that reduce |
| 6 | visual motion and density for screen-reader and low-motion users. |
| 7 | |
| 8 | ## Quick reference |
| 9 | |
| 10 | | Toggle | Default | Effect | |
| 11 | | --- | --- | --- | |
| 12 | | `NO_ANIMATIONS=1` env var | unset | At startup, forces `low_motion = true` and `fancy_animations = false`. Overrides whatever's saved in `settings.toml`. | |
| 13 | | `CODEWHALE_ASCII_SAFE=1` env var | unset | Replaces decorative Unicode and box-drawing marks with narrow ASCII at the terminal backend. Labels, focus, state, and controls remain available. | |
| 14 | | `low_motion` setting | `false` | Freezes decorative and state animation without changing model text delivery. The footer water strip is controlled separately by `fancy_animations`. | |
| 15 | | `fancy_animations` setting | `true` | Enables expressive live-state chrome. Set to `false` to keep live-turn chrome still. | |
| 16 | | `ocean_treatment` setting | `ombre` | Chooses the background appearance: `ombre` paints the state-reactive water column; `flat` uses the plain theme surface. Both keep the same state marks and idle ambient life; appearance is independent of motion settings. | |
| 17 | | `status_indicator` setting | `cw` | Static typographic header mark. Set to `whale` or `dots` for the legacy animations, or `off` to hide it. | |
| 18 | | `calm_mode` setting | `true` | Collapses tool-output details by default and trims status messages. Useful for screen readers that announce every redraw. | |
| 19 | | `show_thinking` setting | `true` | Set to `false` to hide model `reasoning_content` blocks from the TUI presentation. Canonical session/replay receipts remain unchanged. | |
| 20 | | `thinking_default_expanded` setting | `false` | Set to `true` to expand visible thinking blocks initially. Space still collapses or expands the selected block. | |
| 21 | | `show_tool_details` setting | `false` | Set to `true` to expand tool calls inline; details remain available on demand either way. | |
| 22 | | `inline_diffs` setting | `full` | Use `summary` or `off` to reduce inline File-change density. Exact applied evidence remains available with Alt/Option+V in every mode. | |
| 23 | |
| 24 | ## Color contrast guarantees |
| 25 | |
| 26 | The palette enforces WCAG contrast floors in two places, and this is what |
| 27 | the code actually guarantees — no more: |
| 28 | |
| 29 | * **At draw time**, every text cell is lifted to a 4.5:1 contrast ratio |
| 30 | against the surface it will actually render on (`enforce_cell_contrast` in |
| 31 | the terminal backend). Frame chrome (borders, block glyphs) is not clamped, |
| 32 | and community presets that own a full custom palette (Catppuccin, Tokyo |
| 33 | Night, Dracula, Gruvbox, Claude, Matrix, Solarized Light, Terminal) are |
| 34 | exempt from this draw-time pass because their authors tuned those pairs. |
| 35 | * **Per theme**, an audit (`theme_contrast_violations`) holds every |
| 36 | selectable preset to the same floors: body, soft, and muted text at 4.5:1 |
| 37 | on every primary surface (including selection and error surfaces); hint and |
| 38 | dim text at 3:1; status, warning, success, and info roles at 3:1 because |
| 39 | they are redundant — every status also carries a glyph and a word label, |
| 40 | so color is never the only channel. Diff foreground/background pairs are |
| 41 | held to 3:1. |
| 42 | * The **Terminal** (transparent) theme is exempt by design: it paints |
| 43 | `Color::Reset` surfaces and ANSI accents so the host terminal's own scheme |
| 44 | shows through. Those colors are terminal-owned and cannot be measured, so |
| 45 | the audit skips them rather than claiming a pass |
| 46 | (`theme_uses_terminal_owned_surfaces` makes the exemption explicit). |
| 47 | * The **Grayscale** theme's "Color-minimal high contrast" tagline is |
| 48 | enforced: its body text hierarchy clears 4.5:1 on every surface. |
| 49 | * The ASCII tier (`CODEWHALE_ASCII_SAFE=1`) keeps labels, focus, and state |
| 50 | available without decorative glyphs, so the non-color redundancy above |
| 51 | survives in the plainest rendering mode. |
| 52 | |
| 53 | ## Standard env-var surface |
| 54 | |
| 55 | Set these in your shell profile so they apply to every session: |
| 56 | |
| 57 | ```bash |
| 58 | # Force low-motion + no fancy animations. |
| 59 | export NO_ANIMATIONS=1 |
| 60 | |
| 61 | # Force the terminal-safe ASCII rendering tier. |
| 62 | export CODEWHALE_ASCII_SAFE=1 |
| 63 | |
| 64 | # Optional: respect the wider terminal-color convention. |
| 65 | export NO_COLOR=1 # honored by the underlying ratatui backend |
| 66 | ``` |
| 67 | |
| 68 | `NO_ANIMATIONS` accepts any of `1`, `true`, `yes`, or `on` |
| 69 | (case-insensitive). Any other value (including `0`, `false`, empty, |
| 70 | or unset) leaves your saved settings alone. |
| 71 | |
| 72 | The override is applied once at startup. Changing the env var |
| 73 | mid-session has no effect — settings are only re-read on the next |
| 74 | launch. |
| 75 | |
| 76 | ## Configuring via `/settings` |
| 77 | |
| 78 | The same toggles are reachable from the command palette: |
| 79 | |
| 80 | * `/settings set low_motion on` |
| 81 | * `/settings set fancy_animations off` |
| 82 | * `/settings set calm_mode on` |
| 83 | * `/settings set status_indicator off` |
| 84 | |
| 85 | Settings written this way persist to `~/.codewhale/settings.toml` on new |
| 86 | installs, with legacy `~/.deepseek/settings.toml` and platform config-dir |
| 87 | settings kept as compatibility fallbacks. |
| 88 | The `NO_ANIMATIONS` env var still wins at startup if it's set, so |
| 89 | unsetting the env var is the way to honor your saved choice. |
| 90 | |
| 91 | Tilix and Terminator sessions automatically start in low-motion mode because |
| 92 | those VTE-based terminals have reported visible redraw flicker during active |
| 93 | turns. You can still override the saved settings after launch if your terminal |
| 94 | version renders cleanly. |
| 95 | |
| 96 | ## Notes for screen-reader users |
| 97 | |
| 98 | * `low_motion` slows the idle redraw loop to ~120ms per frame and freezes state |
| 99 | markers without synthesizing or throttling model text. Combined with |
| 100 | `calm_mode`, the redraw rate stays low enough that VoiceOver / |
| 101 | Orca announcements track linearly with model output instead of |
| 102 | re-reading the whole screen on each tick. |
| 103 | * The transcript is pure text — no images or canvas rendering — so |
| 104 | any terminal that integrates with the platform's accessibility |
| 105 | service (e.g. macOS Terminal.app, iTerm2, Ghostty, Windows |
| 106 | Terminal) will pass the rendered content straight through. |
| 107 | * If you find a UI surface that still produces motion when |
| 108 | `low_motion = true`, please file an issue against |
| 109 | [`PRIOR: Screen-reader / accessibility flag`](https://github.com/Hmbown/CodeWhale/issues/450) |
| 110 | with a screenshot or terminal recording. |
| 111 | |
| 112 | ## Related issues / history |
| 113 | |
| 114 | * [#450](https://github.com/Hmbown/CodeWhale/issues/450) — |
| 115 | documenting the existing flag, adding the `NO_ANIMATIONS` |
| 116 | startup overlay, and writing this page. |
| 117 | * [#449](https://github.com/Hmbown/CodeWhale/issues/449) — |
| 118 | footer statusline now uses the active theme's contrast pair |
| 119 | instead of a bespoke palette. |
| 120 |