huh

A simple, powerful Go library for building interactive terminal forms and prompts, with theming and accessibility built in.

Library
Go
vv1.0.0
7,135stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
70/100Good
Development Activity68
Maintenance68
Community56
Maturity48
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
83/100Excellent
Architecture84
Code Quality78
Innovation80
Learning Curve90

huh is a Go library from Charm for building interactive terminal forms and prompts. Forms are composed from groups of fields — input, text, select, multi-select, confirm, and note — and can either run standalone as a blocking call or be embedded directly inside a Bubble Tea application as a nested model. Fields support validation functions, dynamic titles and options that recompute based on other field values, and a first-class accessible mode that drops the TUI in favor of plain sequential prompts for screen readers.

The library ships five built-in themes (Charm, Dracula, Catppuccin, Base 16, Default) built on Lip Gloss styling, and a companion spinner package for indicating background activity once a form is submitted. It’s widely used across the Charm ecosystem and by third-party Go CLIs — including GitHub’s own gh extensions — as the default way to collect structured, validated input from a terminal user without hand-rolling prompt loops.

What You Get

  • Six field types — Input, Text, Select, MultiSelect, Confirm, and FilePicker — each configurable via a fluent, chainable builder API
  • Forms organized into Groups (pages) with automatic navigation, per-field validation, and error display before advancing
  • Dynamic fields via TitleFunc/OptionsFunc/DescriptionFunc that recompute based on bindings to other field values, with built-in caching
  • Five predefined themes (Charm, Dracula, Catppuccin, Base 16, Default) plus a full custom Lip Gloss theme abstraction
  • A dedicated accessible mode (WithAccessible) that renders plain sequential prompts instead of a TUI for screen-reader users
  • A standalone spinner sub-package for showing background activity with either an Action-callback style or a context-driven style
  • Native embedding inside Bubble Tea apps as a nested tea.Model, or standalone blocking use via form.Run() / field.Run()

Common Use Cases

  • Interactive CLI onboarding — collecting project name, environment, and configuration choices when scaffolding a new project
  • Git/GitHub workflow prompts — commit message, PR description, and reviewer selection forms in custom Git tooling
  • Ordering/checkout-style demos and internal tools — multi-group forms with conditional, dynamically-populated fields (e.g. country → state)
  • Accessible terminal surveys and setup wizards where screen-reader compatibility is a hard requirement
  • Adding structured, validated user input to existing Bubble Tea TUIs without building a custom form component from scratch

Under The Hood

Architecture huh centers on a Form (form.go) that owns a selector.Selector[*Group] — a small internal cursor type (internal/selector/selector.go) shared by both forms-over-groups and groups-over-fields navigation. Each Group similarly wraps a selector.Selector[Field], and every field type (field_input.go, field_select.go, field_multiselect.go, field_confirm.go, field_text.go, field_filepicker.go, field_note.go) implements a common Field interface that embeds a compat.Model (Bubble Tea’s Model, aliased through internal/compat to bridge the v1/v2 Bubble Tea API) plus Blur/Focus/Error/Run/RunAccessible/Skip/Zoom. This lets Form.Update in form.go dispatch tea.Msg values down through the active group to the active field uniformly, and lets any field also run standalone via its own Run(). Dynamic values (titles, descriptions, options) are modeled by a generic Eval[T] type (eval.go) that hashes its declared bindings via mitchellh/hashstructure and only recomputes + emits an update message when the hash changes, with an in-memory cache keyed by hash. Accessible mode is a genuinely separate code path (internal/accessibility) rather than a rendering flag on the TUI path, so screen-reader support isn’t an afterthought bolted onto the Bubble Tea view.

Tech Stack The module (charm.land/huh/v2, go.mod) targets Go 1.25 and sits squarely inside the Charm terminal ecosystem: charm.land/bubbletea/v2 for the Elm-style update loop, charm.land/bubbles/v2 for shared help/viewport/key components, and charm.land/lipgloss/v2 for styling — plus charmbracelet/x/ansi, x/term, and x/xpty for lower-level terminal and pty handling. Theming pulls in catppuccin/go for one of its five preset palettes, and dynamic-field caching depends on mitchellh/hashstructure/v2 for stable struct hashing. There’s no external build tooling beyond go build/go test and a Makefile; CI (.github/workflows/lint.yml, build.yml) delegates to Charm’s own shared charmbracelet/meta reusable workflows rather than a bespoke pipeline.

Code Quality huh_test.go carries 32 top-level test functions plus a dedicated zz_resize_width_test.go and a spinner_test.go (12 tests) in the spinner sub-package — solid coverage of form/group/field state transitions, though there’s no single dominant assertion framework beyond stdlib testing. Error handling is explicit and typed: sentinel errors (ErrUserAborted, ErrTimeout, ErrTimeoutUnsupported) are exported for callers to check with errors.Is, and field-level validation returns plain error values surfaced through Field.Error() rather than being swallowed. Naming is consistent and idiomatic Go (exported With* option methods, *Func variants for dynamic fields), and golangci-lint runs in CI against a shared Charm config, giving the codebase consistent static-analysis coverage across the whole org rather than a one-off local config.

API Design The public API is a fluent, chainable builder (huh.NewInput().Title(...).Validate(...).Value(&v)) that reads close to natural language and keeps boilerplate low — a single field can run standalone with .Run(), or be composed into NewGroup(...) and NewForm(...) for multi-page flows, so the same field types scale from a one-line prompt to a full wizard without an API switch. Generics (Select[T], MultiSelect[T]) let option values be any comparable type instead of forcing string-only APIs, and *Func variants (TitleFunc, OptionsFunc) make dependent/dynamic fields an explicit, well-documented escape hatch rather than a workaround. Documentation is strong for a library this size — a long, example-driven README, a dedicated UPGRADE_GUIDE_V2.md for the v1→v2 migration, and 20+ runnable examples under examples/ covering everything from basic forms to Bubble Tea embedding and accessibility.

Used by 6 apps in this directory

Go
73%
Other

Flipt

Devops · Developer Tools

4,884

Git-native feature flag platform that stores, versions, and deploys feature toggles directly in your own Git repositories with no external database required.

View details
89
Repo Health
83
Technical
70
Dependency
Built with
Go73%
TypeScript26%
Updated yesterday
Go
84%
MIT

Hatchet

AI Development · Developer Tools · Automation

7,812

A Postgres-backed orchestration engine for background tasks, AI agents, and durable workflows that replaces Redis queues and multi-datastore durable execution platforms with a single self-hostable service.

View details
88
Repo Health
83
Technical
68
Dependency
Built with
Go84%
PLpgSQL11%
Updated today
Go
95%
MIT

cli

Developer Tools · Team Chat

16,854

The official Lark/Feishu CLI tool built for both humans and AI agents, delivering 200+ commands and 26 AI agent skills across 18 business domains from messaging and calendar to docs, sheets, and approvals.

View details
83
Repo Health
83
Technical
76
Dependency
Built with
Go95%
Updated today
TypeScript
99%
AGPL 3.0

Pangolin

Networking

22,550

An open-source, identity-based zero-trust remote access platform built on WireGuard — a self-hostable alternative to Cloudflare Tunnel and Twingate with SSO, OIDC, and tunneled reverse proxying.

View details
86
Repo Health
68
Technical
72
Dependency
Built with
TypeScript99%
Updated 2 days ago
Go
75%
AGPL 3.0

Teleport

Security · Authentication

20,860

Zero-trust infrastructure access platform that replaces credentials and VPNs with short-lived certificates, SSO, and identity-aware proxies for SSH, Kubernetes, databases, RDP, and AI agents.

View details
94
Repo Health
81
Technical
69
Dependency
Built with
Go75%
TypeScript16%
Updated 2 days ago
Go
99%
Apache 2.0

Tusk

Developer Tools · AI Code Assistants · Devops

143

Record live API traffic and replay it as deterministic, sandboxed tests, plus AI code review and unit test generation, all from one Go CLI built by YC W2024's Use-Tusk.

View details
43
Repo Health
77
Technical
76
Dependency
Built with
Go99%
Updated 3 months ago

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search