feat(theme): user-configurable color themes

Description

Adds a theme system so users can customize glab's terminal colors. The active theme controls fang's help and error rendering, huh's interactive prompts, and the ANSI color layer used in command output — all three surfaces now read from the same resolved palette.

The built-in gitlab theme preserves existing colors exactly. Everything else is opt-in.

Theme layer (internal/theme/): Refactored GitLabColors into a generic Colors struct with semantic roles (Primary, Secondary, Info, Success, Warning, Error, Text, Subtle) and a Theme type holding separate light and dark palettes. FangColorScheme and HuhTheme are now parameterised on these structs rather than hardcoding hex values. This also fixes a pre-existing bug where HuhTheme re-derived its own light/dark hex constants inline instead of reading from the shared palette.

Registry (internal/theme/registry/): Discovers built-in themes (plain Go values, no embed or parsing) and user-authored YAML files from <ConfigDir>/themes/*.yml. Built-ins win on name collision. The YAML parser validates #RRGGBB hex format and requires all 8 semantic fields in both light and dark palettes.

Config key: theme added to KeySchema with GLAB_THEME env override, fallback to gitlab, and UserSettable: true.

Wiring (cmd/glab/main.go): Active theme resolves once at startup, falls back silently to gitlab on error, then threads into fang via WithColorSchemeFunc and into IOStreams via a new WithTheme option.

glab theme commands:

Command What it does
glab theme list Table of available themes with source and active marker
glab theme get [name] Shows the palette (light + dark hex values) for a theme
glab theme set <name> Validates against the registry, then writes the theme config key
glab theme create <name> Scaffolds a new YAML file from a seed theme; opens $EDITOR with --edit
glab theme edit <name> Opens a user theme in $EDITOR, validates before saving, rejects built-ins
glab theme path Prints <ConfigDir>/themes

Theme file format — a YAML file with light and dark palette blocks:

name: mytheme
light:
  primary: "#FC6D26"
  secondary: "#7759C2"
  info: "#1068BF"
  success: "#217645"
  warning: "#C97A00"
  error: "#C91C00"
  text: "#171321"
  subtle: "#6B6B73"
dark:
  # same fields, dark-background variants

N/A — discussion happened in planning session, no upstream issue yet.

How has this been tested?

Unit tests cover the registry (parsing, validation, round-trip marshal, builtin precedence, missing directory) and the list, get, and set commands via cmdtest.SetupCmdForTest. The TestParse_InvalidHex test caught a real validation bug during development — lipgloss.Color("notacolor") returns NoColor{} rather than nil, so the alpha check was wrong; fixed with explicit hex-format validation.

All existing tests pass (go test ./...). make gen-docs regenerates cleanly and the new docs/source/theme/ pages are included in the commit.

Merge request reports

Loading
Loading