Source: external review report, 2026-08-24 (notable exclusion #2)
Gap
Colors are hardcoded constants (SHELLFRAME_GRAY, etc.) except toast's ad-hoc theme override. Any embedder wanting brand colors must sed the source.
What it needs
- A palette of semantic roles, not raw colors:
SHELLFRAME_THEME_BORDER, _TITLE, _ACCENT, _MUTED, _ERROR, _SUCCESS, _SELECTED_BG, _SELECTED_FG
- Defaults set with
: "${SHELLFRAME_THEME_BORDER:=$'\033[90m'}" so consumers override by exporting before source shellframe.sh
- Widgets read roles, never raw constants; keep the old
SHELLFRAME_GRAY names as aliases for one release
- Fold toast's override into the same mechanism
- Optional:
shellframe_theme_load path/to/theme.sh and one or two shipped themes (default, mono/no-color)
NO_COLOR env var honored (https://no-color.org)
Tests
- Unit: export a role, source, render confirm → escape present in output
- Unit:
NO_COLOR=1 → no SGR sequences emitted
Effort: M
Deps: #42 (H2) (so %b is only ever applied to theme constants — theming makes that boundary explicit)
Source: external review report, 2026-08-24 (notable exclusion #2)
Gap
Colors are hardcoded constants (
SHELLFRAME_GRAY, etc.) except toast's ad-hoc theme override. Any embedder wanting brand colors mustsedthe source.What it needs
SHELLFRAME_THEME_BORDER,_TITLE,_ACCENT,_MUTED,_ERROR,_SUCCESS,_SELECTED_BG,_SELECTED_FG: "${SHELLFRAME_THEME_BORDER:=$'\033[90m'}"so consumers override by exporting beforesource shellframe.shSHELLFRAME_GRAYnames as aliases for one releaseshellframe_theme_load path/to/theme.shand one or two shipped themes (default, mono/no-color)NO_COLORenv var honored (https://no-color.org)Tests
NO_COLOR=1→ no SGR sequences emittedEffort: M
Deps: #42 (H2) (so
%bis only ever applied to theme constants — theming makes that boundary explicit)