πΉ Go Fan Report: Lip Gloss v2
Module Overview
charm.land/lipgloss/v2 is Charm's declarative, CSS-like terminal styling library β colors, borders, padding/alignment, layout composition, plus the table, tree, and list sub-packages. It's the backbone of every human-facing surface in gh-aw. We're on v2.0.4, the latest release (2026-06-12) π
Current Usage in gh-aw
gh-aw uses Lip Gloss idiomatically and keeps it well-centralized in pkg/styles.
- Files: 8 non-test files
- Import Count: 113
lipgloss.* references
- Key APIs Used:
NewStyle (55Γ), Color (40Γ), Style, border constructors (RoundedBorder/NormalBorder/DoubleBorder/...), Fprintf, LightDark, JoinVertical, HasDarkBackground, plus the table and tree sub-packages.
Where it lives
pkg/styles/theme.go β single source of truth: custom adaptiveColor type + Dracula-inspired palette + ~40 pre-built styles.
pkg/styles/huh_theme.go β maps the palette onto huh forms via lipgloss.LightDark(isDark).
pkg/console/console.go β helpers; uses lipgloss/v2/table, JoinVertical, borders, TTY-gated applyStyle.
pkg/cli/status_command.go, pkg/cli/mcp_inspect.go β lipgloss/v2/tree with EnumeratorStyle/ItemStyle.
pkg/cli/compile_schedule_calendar.go β hand-rolled schedule heatmap.
pkg/logger/logger.go β namespace coloring + lipgloss.Fprintf.
Research Findings
The big v2 story is that the global renderer and automatic color-profile detection were removed in v2.0.0. In v2, Style.Render emits ANSI at the style's declared color (truecolor for hex values) unconditionally β it does not consult NO_COLOR, TERM, or the terminal's actual color depth. Degradation is now the caller's responsibility via the github.com/charmbracelet/colorprofile package (a colorprofile.Writer reads os.Environ() and downgrades/strips ANSI).
Recent Updates
Best Practices
- Route styled output through
colorprofile.NewWriter(w, os.Environ()) β the canonical v2 replacement for v1's implicit renderer.
- Use
lipgloss.LightDark(isDark) for light/dark mapping (already done in huh_theme.go).
Improvement Opportunities
π Quick Wins
compile_schedule_calendar.go:203 returns the zero value lipgloss.Style{} for the non-TTY branch, while every other site uses lipgloss.NewStyle(). Identical output β swap for NewStyle() for uniformity.
pkg/logger/logger.go hand-builds a 12-entry colorPalette with duplicated colors; deriving it from a smaller base slice would prevent drift.
β¨ Feature Opportunities
- Honor
NO_COLOR and degrade color depth via colorprofile.Writer. Today, coloring is gated only on isTTY(). Consequences: (1) a user with NO_COLOR=1 on a TTY still gets ANSI, and (2) 16-/256-color terminals receive raw truecolor sequences. colorprofile is already an indirect dependency (v0.4.3) β wrapping the stdout/stderr write path with colorprofile.NewWriter(w, os.Environ()) would honor NO_COLOR/CLICOLOR_FORCE and auto-degrade, localized to the write path rather than each style. This is the highest-value item. π―
π Best Practice Alignment
- The custom
adaptiveColor (theme.go) and v2's LightDark (huh_theme.go) coexist. Both are valid β adaptiveColor defers the light/dark choice to render time via a global, which is a deliberate, reasonable design. A one-line comment cross-referencing the two would help future contributors pick the right one.
- The Windows
HasDarkBackground guard is well-reasoned and now doubly covered by the v2.0.3 upstream fix β no change needed.
π§ General Improvements
- If
colorprofile.Writer is adopted, the styled boxes (RenderTitleBox, RenderErrorBox) render first and are written after, so the change stays confined to the write path β no per-style edits required.
Recommendations
- (High) Adopt a
colorprofile.Writer on the stdout/stderr write path to honor NO_COLOR/CLICOLOR_FORCE and degrade truecolor for limited terminals.
- (Low) Normalize
lipgloss.Style{} β lipgloss.NewStyle() in compile_schedule_calendar.go.
- (Low) Add a cross-reference comment between
adaptiveColor and LightDark.
Next Steps
- Prototype a
colorprofile-wrapped writer in pkg/console and verify NO_COLOR=1 suppresses ANSI while TTY truecolor is unchanged.
- No version bump needed β already on latest v2.0.4.
Generated by Go Fan πΉ
Module summary saved to: scratchpad/mods/lipgloss.md
Generated by πΉ Go Fan Β· 163.8 AIC Β· β 13.1 AIC Β· β 7.4K Β· β·
πΉ Go Fan Report: Lip Gloss v2
Module Overview
charm.land/lipgloss/v2is Charm's declarative, CSS-like terminal styling library β colors, borders, padding/alignment, layout composition, plus thetable,tree, andlistsub-packages. It's the backbone of every human-facing surface in gh-aw. We're on v2.0.4, the latest release (2026-06-12) πCurrent Usage in gh-aw
gh-aw uses Lip Gloss idiomatically and keeps it well-centralized in
pkg/styles.lipgloss.*referencesNewStyle(55Γ),Color(40Γ),Style, border constructors (RoundedBorder/NormalBorder/DoubleBorder/...),Fprintf,LightDark,JoinVertical,HasDarkBackground, plus thetableandtreesub-packages.Where it lives
pkg/styles/theme.goβ single source of truth: customadaptiveColortype + Dracula-inspired palette + ~40 pre-built styles.pkg/styles/huh_theme.goβ maps the palette onto huh forms vialipgloss.LightDark(isDark).pkg/console/console.goβ helpers; useslipgloss/v2/table,JoinVertical, borders, TTY-gatedapplyStyle.pkg/cli/status_command.go,pkg/cli/mcp_inspect.goβlipgloss/v2/treewithEnumeratorStyle/ItemStyle.pkg/cli/compile_schedule_calendar.goβ hand-rolled schedule heatmap.pkg/logger/logger.goβ namespace coloring +lipgloss.Fprintf.Research Findings
The big v2 story is that the global renderer and automatic color-profile detection were removed in v2.0.0. In v2,
Style.Renderemits ANSI at the style's declared color (truecolor for hex values) unconditionally β it does not consultNO_COLOR,TERM, or the terminal's actual color depth. Degradation is now the caller's responsibility via thegithub.com/charmbracelet/colorprofilepackage (acolorprofile.Writerreadsos.Environ()and downgrades/strips ANSI).Recent Updates
HasDarkBackgroundprobe. gh-aw already guards this on Windows and now benefits from the upstream fix. βBest Practices
colorprofile.NewWriter(w, os.Environ())β the canonical v2 replacement for v1's implicit renderer.lipgloss.LightDark(isDark)for light/dark mapping (already done inhuh_theme.go).Improvement Opportunities
π Quick Wins
compile_schedule_calendar.go:203returns the zero valuelipgloss.Style{}for the non-TTY branch, while every other site useslipgloss.NewStyle(). Identical output β swap forNewStyle()for uniformity.pkg/logger/logger.gohand-builds a 12-entrycolorPalettewith duplicated colors; deriving it from a smaller base slice would prevent drift.β¨ Feature Opportunities
NO_COLORand degrade color depth viacolorprofile.Writer. Today, coloring is gated only onisTTY(). Consequences: (1) a user withNO_COLOR=1on a TTY still gets ANSI, and (2) 16-/256-color terminals receive raw truecolor sequences.colorprofileis already an indirect dependency (v0.4.3) β wrapping the stdout/stderr write path withcolorprofile.NewWriter(w, os.Environ())would honorNO_COLOR/CLICOLOR_FORCEand auto-degrade, localized to the write path rather than each style. This is the highest-value item. π―π Best Practice Alignment
adaptiveColor(theme.go) and v2'sLightDark(huh_theme.go) coexist. Both are valid βadaptiveColordefers the light/dark choice to render time via a global, which is a deliberate, reasonable design. A one-line comment cross-referencing the two would help future contributors pick the right one.HasDarkBackgroundguard is well-reasoned and now doubly covered by the v2.0.3 upstream fix β no change needed.π§ General Improvements
colorprofile.Writeris adopted, the styled boxes (RenderTitleBox,RenderErrorBox) render first and are written after, so the change stays confined to the write path β no per-style edits required.Recommendations
colorprofile.Writeron the stdout/stderr write path to honorNO_COLOR/CLICOLOR_FORCEand degrade truecolor for limited terminals.lipgloss.Style{}βlipgloss.NewStyle()incompile_schedule_calendar.go.adaptiveColorandLightDark.Next Steps
colorprofile-wrapped writer inpkg/consoleand verifyNO_COLOR=1suppresses ANSI while TTY truecolor is unchanged.Generated by Go Fan πΉ
Module summary saved to: scratchpad/mods/lipgloss.md