okami.mom/albedo
git clone https://git.nkp.pet/okami.mom/albedo
f7fcae1
main
Versions and component selection
Resolve the repository before choosing an API
Research snapshot: 2026-09-23. The inspected published documentation showed Bubble Tea v2.0.9, Bubbles v2.2.1, and Lip Gloss v2.0.6. This records what was inspected, not a promise that those are permanently the newest releases or an instruction to upgrade a working project. S01 S02 S03
Start with the repository's go.mod, go.sum, go.work if present, and source imports. Follow the installed APIs and existing conventions. Check each dependency's Go/toolchain requirement before proposing changes. Module resolution may need network access; do not silently modify the module graph just to inspect it.
Useful local checks, when the repository and dependencies are available:
go versiongo list-m allgo test ./...
Use a focused import search as well. Multiple versions can legitimately appear in a dependency graph, but v1 and v2 Tea model/message/component APIs cannot be casually interchanged in one implementation.
For an existing v1 application, fixing a focus bug does not require migration. For an explicit migration, move the interdependent Tea/Bubbles/Lip Gloss layer together, adapt the relevant tests, and verify behavior before optimizing. Bubbles' upgrade guide expressly calls for the companion upgrades. S02
High-impact v1/v2 differences
| Area | Legacy shape | v2 shape to verify in the target version |
|---|---|---|
| Tea import | github.com/charmbracelet/bubbletea | charm.land/bubbletea/v2 |
| Bubbles import | github.com/charmbracelet/bubbles/... | charm.land/bubbles/v2/... |
| Lip Gloss import | github.com/charmbracelet/lipgloss | charm.land/lipgloss/v2 |
| Root view | View() string | View() tea.View, often using tea.NewView(content) |
| Alternate screen | Program options / imperative commands | View.AltScreen |
| Mouse mode | Program options / imperative commands | View.MouseMode |
| Ordinary key switch | case tea.KeyMsg: for a concrete key event | Usually case tea.KeyPressMsg:; tea.KeyMsg is now an interface |
| Key content | Legacy type/rune representation | Code, Text, modifiers; separate press/release concepts |
| Space matching | Often a literal space | String() uses "space"; prefer current key-binding conventions |
| Paste | Legacy key-message conventions | Dedicated paste messages; preserve input component handling |
| Many component dimensions | Public fields | SetWidth, SetHeight, Width(), Height() as applicable |
| Viewport creation | viewport.New(width, height) | viewport.New(viewport.WithWidth(w), viewport.WithHeight(h)) |
| Several default keymaps | Mutable package variables | Constructors such as DefaultKeyMap() |
| Colors | lipgloss.Color as a string type | lipgloss.Color(...) returns image/color.Color |
| Adaptive color | Root AdaptiveColor | Explicit LightDark or compatibility package |
| Lip Gloss renderer | Renderer-associated styles | Value styles; output-layer color handling |
This is a triage map, not a replacement for the full upgrade guides. Refer to S01, S02, and S03. Do not mechanically convert unrelated packages that retain a github.com/charmbracelet/... module path.
An original minimal v2 method sketch, not a standalone application:
func (m model )View () tea.View {v := tea .NewView (m .renderContent ())v .AltScreen = m .fullScreen return v }
For background-aware styling, the documented v2 pattern requests background color through Tea and reacts to tea.BackgroundColorMsg. Keep a fallback style when no reply arrives. Root model methods return a tea.View; embedded Bubbles often still render strings. Do not change every component's View signature merely because the root signature changed.
Choose components for their interaction semantics
Text input / textarea: use for editing, cursor movement, focus, and paste behavior. Configure their styles and dimensions with the target version's API. Keep app shortcuts from stealing printable input. Do not replace their editing model with ad hoc rune slicing to save a small amount of code.
List: appropriate when its filtering, pagination, selection, and help behavior fit. A custom delegate can preserve a bespoke row design. A simple fixed list may only need a slice and cursor; a huge variable-height transcript may need a specialized view. Do not force all three into one abstraction.
Table: appropriate when column comparison is the main task. Decide what columns survive narrowing and what long values do. A table-shaped display is not necessarily an interactive Bubbles table; static Lip Gloss tables serve a different role.
Viewport: owns scrolling, not necessarily the expensive work of generating all content. Decide whether to wrap, clip, or scroll horizontally. Regenerating content should preserve the user's anchor unless a deliberate navigation action changes it.
Help + key: use a shared vocabulary for routing and hints. Enabled bindings should reflect the active state. A hand-written one-line footer can be sufficient for a truly tiny interaction, but it must not drift from the implementation.
Spinner / progress / timer: choose according to available information. Unknown-duration work needs activity, not a fabricated percentage. Preserve returned scheduling commands and stop inactive animation.
These component categories are documented in the Bubbles catalogue; the selection criteria above are recommendations. S02
Huh: useful for forms, field validation, and accessible prompting. It is not a reason to turn an arbitrary browser into a form. Do not start a second blocking interactive loop inside a running Tea update function; follow documented embedding or handoff patterns. S11
Gum: useful for shell-script composition. Importing an entire application because it contains an appealing picker is usually less appropriate than using the underlying Bubbles or learning its interaction pattern. S07
Glamour: use when Markdown formatting is the task, then cache or schedule expensive rendering appropriately. Wish: investigate when serving a TUI over SSH, with session-local ownership. These are optional capabilities, not default dependencies. S17
Testing dependencies must match too
The inspected legacy github.com/charmbracelet/x/exp/teatest module depends on Bubble Tea v1. The separate module github.com/charmbracelet/x/exp/teatest/v2 exists and imports charm.land/bubbletea/v2. Its inspected go.mod declares Go 1.24.2 and a v2 release-candidate minimum dependency. These are facts about the inspected files, not proof of compatibility with every later release. Select and test an appropriate revision in the target application's graph. S12 S13
The v2 helper supports initial terminal size, program options, sending messages, typing text, waiting for conditions, and reading final model/output with timeouts. Read its current implementation before relying on test lifecycle behavior. A virtual-input test is not equivalent to a real terminal restoration test. S14
1# Versions and component selection 2 3## Resolve the repository before choosing an API 4 5Research snapshot: **2026-09-23**. The inspected published documentation showed Bubble Tea **v2.0.9**, Bubbles **v2.2.1**, and Lip Gloss **v2.0.6**. This records what was inspected, not a promise that those are permanently the newest releases or an instruction to upgrade a working project. [S01](sources.md#s01) [S02](sources.md#s02) [S03](sources.md#s03) 6 7Start with the repository's `go.mod`, `go.sum`, `go.work` if present, and source imports. Follow the installed APIs and existing conventions. Check each dependency's Go/toolchain requirement before proposing changes. Module resolution may need network access; do not silently modify the module graph just to inspect it. 8 9Useful local checks, when the repository and dependencies are available: 10 11``` sh 12go version 13go list -m all 14go test ./... 15``` 16 17Use a focused import search as well. Multiple versions can legitimately appear in a dependency graph, but v1 and v2 Tea model/message/component APIs cannot be casually interchanged in one implementation. 18 19For an existing v1 application, fixing a focus bug does not require migration. For an explicit migration, move the interdependent Tea/Bubbles/Lip Gloss layer together, adapt the relevant tests, and verify behavior before optimizing. Bubbles' upgrade guide expressly calls for the companion upgrades. [S02](sources.md#s02) 20 21## High-impact v1/v2 differences 22 23| Area | Legacy shape | v2 shape to verify in the target version | 24| --- | --- | --- | 25| Tea import | `github.com/charmbracelet/bubbletea` | `charm.land/bubbletea/v2` | 26| Bubbles import | `github.com/charmbracelet/bubbles/...` | `charm.land/bubbles/v2/...` | 27| Lip Gloss import | `github.com/charmbracelet/lipgloss` | `charm.land/lipgloss/v2` | 28| Root view | `View() string` | `View() tea.View`, often using `tea.NewView(content)` | 29| Alternate screen | Program options / imperative commands | `View.AltScreen` | 30| Mouse mode | Program options / imperative commands | `View.MouseMode` | 31| Ordinary key switch | `case tea.KeyMsg:` for a concrete key event | Usually `case tea.KeyPressMsg:`; `tea.KeyMsg` is now an interface | 32| Key content | Legacy type/rune representation | `Code`, `Text`, modifiers; separate press/release concepts | 33| Space matching | Often a literal space | `String()` uses `"space"`; prefer current key-binding conventions | 34| Paste | Legacy key-message conventions | Dedicated paste messages; preserve input component handling | 35| Many component dimensions | Public fields | `SetWidth`, `SetHeight`, `Width()`, `Height()` as applicable | 36| Viewport creation | `viewport.New(width, height)` | `viewport.New(viewport.WithWidth(w), viewport.WithHeight(h))` | 37| Several default keymaps | Mutable package variables | Constructors such as `DefaultKeyMap()` | 38| Colors | `lipgloss.Color` as a string type | `lipgloss.Color(...)` returns `image/color.Color` | 39| Adaptive color | Root `AdaptiveColor` | Explicit `LightDark` or compatibility package | 40| Lip Gloss renderer | Renderer-associated styles | Value styles; output-layer color handling | 41 42This is a triage map, not a replacement for the full upgrade guides. Refer to [S01](sources.md#s01), [S02](sources.md#s02), and [S03](sources.md#s03). Do not mechanically convert unrelated packages that retain a `github.com/charmbracelet/...` module path. 43 44An original minimal v2 **method sketch**, not a standalone application: 45 46``` go 47func ( m model ) View () tea. View { 48v := tea . NewView ( m . renderContent ()) 49v . AltScreen = m . fullScreen 50return v 51} 52``` 53 54For background-aware styling, the documented v2 pattern requests background color through Tea and reacts to `tea.BackgroundColorMsg`. Keep a fallback style when no reply arrives. Root model methods return a `tea.View`; embedded Bubbles often still render strings. Do not change every component's View signature merely because the root signature changed. 55 56## Choose components for their interaction semantics 57 58**Text input / textarea:** use for editing, cursor movement, focus, and paste behavior. Configure their styles and dimensions with the target version's API. Keep app shortcuts from stealing printable input. Do not replace their editing model with ad hoc rune slicing to save a small amount of code. 59 60**List:** appropriate when its filtering, pagination, selection, and help behavior fit. A custom delegate can preserve a bespoke row design. A simple fixed list may only need a slice and cursor; a huge variable-height transcript may need a specialized view. Do not force all three into one abstraction. 61 62**Table:** appropriate when column comparison is the main task. Decide what columns survive narrowing and what long values do. A table-shaped display is not necessarily an interactive Bubbles table; static Lip Gloss tables serve a different role. 63 64**Viewport:** owns scrolling, not necessarily the expensive work of generating all content. Decide whether to wrap, clip, or scroll horizontally. Regenerating content should preserve the user's anchor unless a deliberate navigation action changes it. 65 66**Help + key:** use a shared vocabulary for routing and hints. Enabled bindings should reflect the active state. A hand-written one-line footer can be sufficient for a truly tiny interaction, but it must not drift from the implementation. 67 68**Spinner / progress / timer:** choose according to available information. Unknown-duration work needs activity, not a fabricated percentage. Preserve returned scheduling commands and stop inactive animation. 69 70These component categories are documented in the Bubbles catalogue; the selection criteria above are recommendations. [S02](sources.md#s02) 71 72**Huh:** useful for forms, field validation, and accessible prompting. It is not a reason to turn an arbitrary browser into a form. Do not start a second blocking interactive loop inside a running Tea update function; follow documented embedding or handoff patterns. [S11](sources.md#s11) 73 74**Gum:** useful for shell-script composition. Importing an entire application because it contains an appealing picker is usually less appropriate than using the underlying Bubbles or learning its interaction pattern. [S07](sources.md#s07) 75 76**Glamour:** use when Markdown formatting is the task, then cache or schedule expensive rendering appropriately. **Wish:** investigate when serving a TUI over SSH, with session-local ownership. These are optional capabilities, not default dependencies. [S17](sources.md#s17) 77 78## Testing dependencies must match too 79 80The inspected legacy `github.com/charmbracelet/x/exp/teatest` module depends on Bubble Tea v1. The separate module `github.com/charmbracelet/x/exp/teatest/v2` exists and imports `charm.land/bubbletea/v2`. Its inspected `go.mod` declares Go 1.24.2 and a v2 release-candidate minimum dependency. These are facts about the inspected files, not proof of compatibility with every later release. Select and test an appropriate revision in the target application's graph. [S12](sources.md#s12) [S13](sources.md#s13) 81 82The v2 helper supports initial terminal size, program options, sending messages, typing text, waiting for conditions, and reading final model/output with timeouts. Read its current implementation before relying on test lifecycle behavior. A virtual-input test is not equivalent to a real terminal restoration test. [S14](sources.md#s14)