feat: add CLI status command, rewrite setup wizard, and modernize table renderer

Three interconnected CLI improvements:

New status command (cmd/status.go):
- Fetches live claude.ai subscription data using the claudeai client
- Renders rate-limit windows (5-hour, 7-day all/Opus/Sonnet) with
  color-coded progress bars: green <50%, orange 50-80%, red >80%
- Shows overage spend limits and usage percentage
- Handles partial data gracefully (renders what's available)
- Clear onboarding guidance when no session key is configured

Setup wizard rewrite (cmd/setup.go):
- Replace raw bufio.Reader prompts with charmbracelet/huh multi-step form
- Three form groups: welcome screen, credentials (session key + admin key
  with password echo mode), and preferences (time range + theme select)
- Pre-populates from existing config, preserves existing keys on empty input
- Dracula theme for the form UI
- Graceful Ctrl+C handling via huh.ErrUserAborted

Table renderer modernization (internal/cli/render.go):
- Replace 120-line manual box-drawing table renderer with lipgloss/table
- Automatic column width calculation, rounded borders, right-aligned
  numeric columns (all except first)
- Filter out "---" separator sentinels (not supported by lipgloss/table)
- Remove unused style variables (valueStyle, costStyle, tokenStyle,
  warnStyle) and Table.Widths field

Config display update (cmd/config_cmd.go):
- Show claude.ai session key and org ID in config output

Dependencies (go.mod):
- Add charmbracelet/huh v0.8.0 for form-based TUI wizards
- Upgrade golang.org/x/text v0.3.8 -> v0.23.0
- Add transitive deps: catppuccin/go, harmonica, hashstructure, etc.
This commit is contained in:
teernisse
2026-02-20 16:07:40 -05:00
parent 547d402578
commit e241ee3966
6 changed files with 389 additions and 217 deletions

View File

@@ -1,3 +1,4 @@
// Package cmd implements the cburn CLI commands.
package cmd
import (
@@ -24,7 +25,7 @@ func runConfig(_ *cobra.Command, _ []string) error {
return err
}
fmt.Printf(" Config file: %s\n", config.ConfigPath())
fmt.Printf(" Config file: %s\n", config.Path())
if config.Exists() {
fmt.Println(" Status: loaded")
} else {
@@ -40,6 +41,18 @@ func runConfig(_ *cobra.Command, _ []string) error {
}
fmt.Println()
fmt.Println(" [Claude.ai]")
sessionKey := config.GetSessionKey(cfg)
if sessionKey != "" {
fmt.Printf(" Session key: %s\n", maskAPIKey(sessionKey))
} else {
fmt.Println(" Session key: not configured")
}
if cfg.ClaudeAI.OrgID != "" {
fmt.Printf(" Org ID: %s\n", cfg.ClaudeAI.OrgID)
}
fmt.Println()
fmt.Println(" [Admin API]")
apiKey := config.GetAdminAPIKey(cfg)
if apiKey != "" {