πΉ Go Fan Report: huh (charm.land/huh/v2)
Module Overview
huh is Charm's library for building interactive terminal forms and prompts β inputs, selects, multi-selects, confirms, text areas, notes, and file pickers β with theming, validation, keymaps, and an accessible (non-decorated) mode. In gh-aw it powers every interactive CLI prompt: gh aw add, gh aw run, engine/schedule selection, and secret entry.
Current Usage in gh-aw
- Files: 15 non-test
.go files import charm.land/huh/v2
- Version:
v2.0.3 (latest release; upstream pushed 2026-07-06 but only dep-bump/chore commits since v2.0.3 β no new API to adopt)
- Key APIs Used:
NewForm, NewGroup, NewInput (+EchoModePassword, Validate), NewSelect, NewMultiSelect, NewText, NewConfirm, NewOption, ThemeBase/ThemeFunc, WithTheme, WithAccessible, Run, RunWithContext
The integration is genuinely well-structured, with two clean abstraction layers:
pkg/styles/huh_theme.go β a huh.ThemeFunc mapping the Dracula palette via huh.ThemeBase + lipgloss LightDark.
pkg/console/prompt_form.go β NewForm/NewInputForm/NewSelectForm/NewConfirmForm wrappers that centralize theme + WithAccessible(...).
Research Findings
i Verified against form.go @ tag v2.0.3. huh exposes sentinel errors specifically so callers can distinguish outcomes:
var ErrUserAborted = errors.New("user aborted") // Ctrl+C / Esc before submit
var ErrTimeout = errors.New("timeout")
var ErrTimeoutUnsupported = errors.New("timeout is not supported in accessible mode")
Run/RunWithContext return ErrUserAborted when the user cancels.
Recent Updates
No functional changes since v2.0.3 (2026-03-10) β recent activity is dependency bumps only. The current pin is up to date.
Best Practices
- Distinguish deliberate cancellation (
ErrUserAborted) from real errors.
- Keep theme + accessible-mode application centralized (gh-aw already does this well).
- Thread
context into prompts so they're cancellable.
Improvement Opportunities
π Quick Wins
- Handle
huh.ErrUserAborted explicitly β the one concrete gap. No call site anywhere checks errors.Is(err, huh.ErrUserAborted). A deliberate Ctrl+C during secret entry currently surfaces as a hard failure, e.g. failed to get Copilot token: user aborted (pkg/cli/engine_secrets.go:324/368/417). Add a console.IsCancelled(err) helper and let callers return a clean cancellation (friendly Cancelled. message, exit code 130) instead of wrapping it as an error.
pkg/cli/run_interactive.go:351 returns false on any Run error, collapsing abort and genuine failures into one path β distinguishing them would sharpen logs/behavior.
β¨ Feature Opportunities
WithTimeout on secret/token prompts to avoid hanging indefinitely in semi-interactive CI, paired with errors.Is(err, huh.ErrTimeout). (Note: timeouts are unsupported in accessible mode β guard with ErrTimeoutUnsupported.)
π Best Practice Alignment
- Context consistency β
pkg/console confirm/input/list use the context-less form.Run(), while pkg/cli/* uses form.RunWithContext(ctx). The console prompts therefore can't be cancelled via context. Consider threading ctx through the console helpers (or adding *WithContext variants) for uniform, cancellable prompts.
π§ General Improvements
- Keep new interactive surfaces going through the
NewForm wrappers rather than calling huh.NewForm(...).WithTheme(...) directly, so theming/accessibility stay in one place. (No violations found today β noting to preserve the pattern.)
Recommendations
- (High, low-effort) Add
console.IsCancelled(err) around huh.ErrUserAborted and adopt it at the secret-entry call sites so cancellation is a graceful exit, not a failure message.
- (Medium) Thread
context through pkg/console confirm/input/list for cancellable, consistent prompts.
- (Low/optional) Add
WithTimeout + ErrTimeout handling on token prompts for CI robustness.
Next Steps
Generated by Go Fan
Module summary saved to: scratchpad/mods/charmbracelet-huh.md
Generated by πΉ Go Fan Β· 193.6 AIC Β· β 13.1 AIC Β· β 7.3K Β· β·
πΉ Go Fan Report: huh (charm.land/huh/v2)
Module Overview
huhis Charm's library for building interactive terminal forms and prompts β inputs, selects, multi-selects, confirms, text areas, notes, and file pickers β with theming, validation, keymaps, and an accessible (non-decorated) mode. In gh-aw it powers every interactive CLI prompt:gh aw add,gh aw run, engine/schedule selection, and secret entry.Current Usage in gh-aw
.gofiles importcharm.land/huh/v2v2.0.3(latest release; upstream pushed 2026-07-06 but only dep-bump/chore commits since v2.0.3 β no new API to adopt)NewForm,NewGroup,NewInput(+EchoModePassword,Validate),NewSelect,NewMultiSelect,NewText,NewConfirm,NewOption,ThemeBase/ThemeFunc,WithTheme,WithAccessible,Run,RunWithContextThe integration is genuinely well-structured, with two clean abstraction layers:
pkg/styles/huh_theme.goβ ahuh.ThemeFuncmapping the Dracula palette viahuh.ThemeBase+ lipglossLightDark.pkg/console/prompt_form.goβNewForm/NewInputForm/NewSelectForm/NewConfirmFormwrappers that centralize theme +WithAccessible(...).Research Findings
i Verified against
form.go@ tagv2.0.3. huh exposes sentinel errors specifically so callers can distinguish outcomes:Run/RunWithContextreturnErrUserAbortedwhen the user cancels.Recent Updates
No functional changes since v2.0.3 (2026-03-10) β recent activity is dependency bumps only. The current pin is up to date.
Best Practices
ErrUserAborted) from real errors.contextinto prompts so they're cancellable.Improvement Opportunities
π Quick Wins
huh.ErrUserAbortedexplicitly β the one concrete gap. No call site anywhere checkserrors.Is(err, huh.ErrUserAborted). A deliberate Ctrl+C during secret entry currently surfaces as a hard failure, e.g.failed to get Copilot token: user aborted(pkg/cli/engine_secrets.go:324/368/417). Add aconsole.IsCancelled(err)helper and let callers return a clean cancellation (friendlyCancelled.message, exit code 130) instead of wrapping it as an error.pkg/cli/run_interactive.go:351returnsfalseon anyRunerror, collapsing abort and genuine failures into one path β distinguishing them would sharpen logs/behavior.β¨ Feature Opportunities
WithTimeouton secret/token prompts to avoid hanging indefinitely in semi-interactive CI, paired witherrors.Is(err, huh.ErrTimeout). (Note: timeouts are unsupported in accessible mode β guard withErrTimeoutUnsupported.)π Best Practice Alignment
pkg/consoleconfirm/input/list use the context-lessform.Run(), whilepkg/cli/*usesform.RunWithContext(ctx). The console prompts therefore can't be cancelled via context. Consider threadingctxthrough the console helpers (or adding*WithContextvariants) for uniform, cancellable prompts.π§ General Improvements
NewFormwrappers rather than callinghuh.NewForm(...).WithTheme(...)directly, so theming/accessibility stay in one place. (No violations found today β noting to preserve the pattern.)Recommendations
console.IsCancelled(err)aroundhuh.ErrUserAbortedand adopt it at the secret-entry call sites so cancellation is a graceful exit, not a failure message.contextthroughpkg/consoleconfirm/input/list for cancellable, consistent prompts.WithTimeout+ErrTimeouthandling on token prompts for CI robustness.Next Steps
Generated by Go Fan
Module summary saved to: scratchpad/mods/charmbracelet-huh.md