Skip to content

Modernizes the CRE CLI's user interface by integrating the Charm ecosystem#243

Open
ejacquier wants to merge 59 commits intomainfrom
feature/charm-lib-refactoring
Open

Modernizes the CRE CLI's user interface by integrating the Charm ecosystem#243
ejacquier wants to merge 59 commits intomainfrom
feature/charm-lib-refactoring

Conversation

@ejacquier
Copy link
Contributor

Summary

This PR modernizes the CRE CLI's user interface by integrating the Charm ecosystem (Lipgloss, Huh, Bubble Tea). This is a view-layer only refactoring - no business logic or Cobra command structure was modified.

Why This Refactoring?

To build a world-class developer experience, we needed a better foundation. Our previous approach had limitations:

  • No terminal ownership: Simple fmt.Print calls can't handle async operations gracefully
  • Basic prompts: The old promptui library offered limited customization and no modern UX patterns
  • Inconsistent styling: Colors and formatting were applied ad-hoc across commands
  • No async feedback: Long-running operations (API calls, deployments) had no visual feedback

The Charm ecosystem solves these by owning the terminal - it manages the view layer as a proper UI framework, enabling:

  • Spinners for async operations: Visual feedback during network calls, file operations, etc.
  • Rich form inputs: Tab-completion, suggestions, themed styling
  • Consistent branding: Chainlink color palette applied uniformly
  • Graceful interruption: Users can cancel long operations with Escape/Ctrl+C

Key Changes

1. New UI Package (internal/ui/)

Centralized styling and output functions:

// Before (scattered across codebase)
fmt.Println("Operation successful")
fmt.Printf("\033[32m✓\033[0m Done\n")

// After (consistent, branded)
ui.Success("Operation successful")
ui.Error("Something went wrong")
ui.Warning("Deprecated feature")
ui.Dim("Secondary information")

2. Chainlink-Branded Theme

All interactive elements use the Chainlink color palette:

  • Blue 500 (#375BD2): Primary actions, spinners, focused elements
  • Green: Success states
  • Orange: Errors (high contrast)
  • Gray scale: Secondary text, disabled states

3. Spinner for Async Operations

Reference-counted spinner that handles concurrent operations:

spinner := ui.GlobalSpinner()
spinner.Start("Connecting to API...")
// ... async work ...
spinner.Update("Processing response...")
// ... more work ...
spinner.Stop()

4. Modern Form Inputs with Huh

Replaced promptui with huh forms featuring:

  • Tab-completion for default values
  • Chainlink-themed styling
  • Keyboard navigation (Enter to submit, Escape to cancel)
huh.NewInput().
    Title("Project name").
    Placeholder(defaultName).
    Suggestions([]string{defaultName}).
    Value(&projName)

5. Enhanced Error Handling

New helpers for actionable error messages:

ui.ErrorWithHelp("Connection failed", "Check your network connection")

ui.ErrorWithSuggestions("Invalid config", []string{
    "Run 'cre init' to create a new project",
    "Check the config file syntax",
})

6. Graceful Cancellation

Long-running operations (like cre login) now support Escape/Ctrl+C with proper cleanup and user feedback.

What's NOT Changed

  • Cobra command structure: All commands, flags, and arguments unchanged
  • Business logic: API calls, file processing, validation logic untouched
  • Command behavior: Same inputs produce same outputs
  • Configuration: Settings files and environment variables unchanged

Libraries

Library Purpose
Lipgloss Terminal styling (colors, borders, layout)
Huh Interactive forms and prompts
Bubble Tea Terminal UI framework
Bubbles Pre-built components (spinner)

Removed Dependencies

  • promptui - Replaced entirely by huh

Testing

  • All existing tests pass
  • Manual testing of all commands

  - Create internal/ui/ package with centralized Lipgloss styles (styles.go)
  - Add output helpers for consistent styling: Title, Box, Success, Dim, etc.
  - Implement Bubble Tea spinner with reference counting for async operations
  - Add GlobalSpinner singleton for seamless spinner across CLI lifecycle
  - Update PersistentPreRunE to show spinner during initialization
  - Migrate cre init and cre whoami to use shared UI package
  - Add spinner during file generation (copying, generating templates, contracts)
  - Show spinner during Go dependencies installation
  - Display dependencies in styled box after spinner completes
  - Fix Next steps box spacing and formatting
  - Refactor initializeGoModule to return deps instead of printing
  - Add styled template functions (styleTitle, styleSection, styleCommand, styleDim, styleSuccess, styleCode)
  - Update help template to use Lipgloss styling
  - Style section headers, command names, tips, and URLs
  - Improve visual hierarchy and readability
  - Add complete Blocks palette constants (Gray, Blue, Green, Red, Orange, Yellow, Teal, Purple)
  - Use high-contrast colors for dark terminal readability
  - Style titles/commands with Blue 400-500 for visibility
  - Style secondary info with Gray 500 (dimmed)
  - Create custom Huh theme with Blocks colors for forms
  - Update spinner to use Blue 500
  - Add styled title and welcome message using Chainlink theme
  - Add Bubble Tea spinner with progress states throughout auth flow:
    - Preparing authentication
    - Opening browser
    - Waiting for authentication
    - Exchanging authorization code
    - Saving credentials
  - Show styled URL fallback when browser cannot open automatically
  - Display success message with next steps in branded box
  - Update spinner message during org membership retry flow
  - Update tests to include spinner in handler instantiations
  - Add SilenceErrors: true to root command to disable Cobra's default error output
  - Display all user-facing errors with styled ui.Error() in Execute()
  - Errors now show with red color and ✗ prefix consistent with Chainlink theme
  - Internal debug logging via zerolog remains unchanged
  - Add SilenceErrors: true to disable Cobra's default error output
  - Display errors with styled ui.Error() (red with ✗ prefix)
  - Set SilenceUsage in PersistentPreRunE to hide usage for runtime errors
  - Keep usage/suggestions visible for command typos and flag errors
    - Replaced prompt.YesNoPrompt with huh.NewConfirm forms
    - Removed stdin io.Reader parameter
  2. Updated cmd/creinit/creinit.go:
    - Updated call sites to match new function signatures
  3. Updated cmd/secrets/common/handler.go:
    - Replaced ~25 fmt.Print* calls with ui.* functions
  4. Updated cmd/workflow/simulate/telemetry_writer.go:
    - Replaced fmt.Printf with ui.Printf
    - Removed unused fmt import
  5. Deleted internal/prompt/ directory:
    - Removed entire old promptui-based package
  6. Cleaned cmd/common/utils.go:
    - Removed unused MustGetUserInputWithPrompt function
    - Removed unused bufio and errors imports
  7. Dependencies cleaned (go mod tidy):
    - Removed github.com/manifoldco/promptui
    - Removed github.com/chzyer/readline
@github-actions
Copy link

🚀 Preview Build Artifacts

You can download the preview builds for this PR from the following URL:

https://github.com/smartcontractkit/cre-cli/actions/runs/21969226069

Note: These are preview builds and are not signed.

@github-actions
Copy link

🚀 Preview Build Artifacts

You can download the preview builds for this PR from the following URL:

https://github.com/smartcontractkit/cre-cli/actions/runs/21969768891

Note: These are preview builds and are not signed.

var excludedCommands = map[string]struct{}{
"cre version": {},
"cre login": {},
"cre logout": {},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the token still invalidated on logout when the command is excluded?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it is still invalidated. The isLoadCredentials exclusion only prevents PersistentPreRunE from calling runtimeContext.AttachCredentials().

stderrStr := stderr.String()
// Cobra may say "accepts 1 arg(s)" or "requires" depending on the command definition.
// We just verify stderr is non-empty and stdout doesn't contain the error.
assert.NotEmpty(t, stderrStr, "expected error output on stderr, got nothing.\nSTDOUT: %s", stdout.String())

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we assert stdout?

ui.WithLabels("Yes, login", "No, cancel"),
)
if formErr != nil {
return fmt.Errorf("authentication required: %w", err)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we also show the formErr?

@github-actions
Copy link

🚀 Preview Build Artifacts

You can download the preview builds for this PR from the following URL:

https://github.com/smartcontractkit/cre-cli/actions/runs/22101301165

Note: These are preview builds and are not signed.

  2. Replaced os.Exit(0) with return errLoginCompleted in PersistentPreRunE after successful auto-login
  3. Added sentinel check in Execute() — when the error is errLoginCompleted, keeps exit code 0, clears the error (so telemetry records success, not failure), and skips ui.Error()
@github-actions
Copy link

🚀 Preview Build Artifacts

You can download the preview builds for this PR from the following URL:

https://github.com/smartcontractkit/cre-cli/actions/runs/22105338078

Note: These are preview builds and are not signed.

@github-actions
Copy link

⚠️ Abigen Fork Check - Update Available

The forked abigen package is outdated and may be missing important updates.

Version Value
Current Fork v1.16.0
Latest Upstream v1.17.0

Action Required

  1. Review abigen changes in upstream (only the accounts/abi/bind directory matters)
  2. Compare with our fork in cmd/generate-bindings/bindings/abigen/
  3. If relevant changes exist, sync them and update FORK_METADATA.md
  4. If no abigen changes, just update the version in FORK_METADATA.md to v1.17.0

Files to Review

  • cmd/generate-bindings/bindings/abigen/bind.go
  • cmd/generate-bindings/bindings/abigen/bindv2.go
  • cmd/generate-bindings/bindings/abigen/template.go

⚠️ Note to PR author: This is not something you need to fix. The Platform Expansion team is responsible for maintaining the abigen fork.

cc @smartcontractkit/bix-framework

@github-actions
Copy link

🚀 Preview Build Artifacts

You can download the preview builds for this PR from the following URL:

https://github.com/smartcontractkit/cre-cli/actions/runs/22106242246

Note: These are preview builds and are not signed.

@github-actions
Copy link

⚠️ Abigen Fork Check - Update Available

The forked abigen package is outdated and may be missing important updates.

Version Value
Current Fork v1.16.0
Latest Upstream v1.17.0

Action Required

  1. Review abigen changes in upstream (only the accounts/abi/bind directory matters)
  2. Compare with our fork in cmd/generate-bindings/bindings/abigen/
  3. If relevant changes exist, sync them and update FORK_METADATA.md
  4. If no abigen changes, just update the version in FORK_METADATA.md to v1.17.0

Files to Review

  • cmd/generate-bindings/bindings/abigen/bind.go
  • cmd/generate-bindings/bindings/abigen/bindv2.go
  • cmd/generate-bindings/bindings/abigen/template.go

⚠️ Note to PR author: This is not something you need to fix. The Platform Expansion team is responsible for maintaining the abigen fork.

cc @smartcontractkit/bix-framework

@github-actions
Copy link

🚀 Preview Build Artifacts

You can download the preview builds for this PR from the following URL:

https://github.com/smartcontractkit/cre-cli/actions/runs/22106748616

Note: These are preview builds and are not signed.

@github-actions
Copy link

⚠️ Abigen Fork Check - Update Available

The forked abigen package is outdated and may be missing important updates.

Version Value
Current Fork v1.16.0
Latest Upstream v1.17.0

Action Required

  1. Review abigen changes in upstream (only the accounts/abi/bind directory matters)
  2. Compare with our fork in cmd/generate-bindings/bindings/abigen/
  3. If relevant changes exist, sync them and update FORK_METADATA.md
  4. If no abigen changes, just update the version in FORK_METADATA.md to v1.17.0

Files to Review

  • cmd/generate-bindings/bindings/abigen/bind.go
  • cmd/generate-bindings/bindings/abigen/bindv2.go
  • cmd/generate-bindings/bindings/abigen/template.go

⚠️ Note to PR author: This is not something you need to fix. The Platform Expansion team is responsible for maintaining the abigen fork.

cc @smartcontractkit/bix-framework

@github-actions
Copy link

🚀 Preview Build Artifacts

You can download the preview builds for this PR from the following URL:

https://github.com/smartcontractkit/cre-cli/actions/runs/22108252983

Note: These are preview builds and are not signed.

@github-actions
Copy link

⚠️ Abigen Fork Check - Update Available

The forked abigen package is outdated and may be missing important updates.

Version Value
Current Fork v1.16.0
Latest Upstream v1.17.0

Action Required

  1. Review abigen changes in upstream (only the accounts/abi/bind directory matters)
  2. Compare with our fork in cmd/generate-bindings/bindings/abigen/
  3. If relevant changes exist, sync them and update FORK_METADATA.md
  4. If no abigen changes, just update the version in FORK_METADATA.md to v1.17.0

Files to Review

  • cmd/generate-bindings/bindings/abigen/bind.go
  • cmd/generate-bindings/bindings/abigen/bindv2.go
  • cmd/generate-bindings/bindings/abigen/template.go

⚠️ Note to PR author: This is not something you need to fix. The Platform Expansion team is responsible for maintaining the abigen fork.

cc @smartcontractkit/bix-framework

@github-actions
Copy link

🚀 Preview Build Artifacts

You can download the preview builds for this PR from the following URL:

https://github.com/smartcontractkit/cre-cli/actions/runs/22109282990

Note: These are preview builds and are not signed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants