中文 | English
Build beautiful, interactive command-line applications with composable components and real-time streaming support.
package main
import (
"context"
"github.com/voocel/coal"
)
func main() {
ctx := context.Background()
// Get user input
name, _ := coal.Input(ctx, "What's your name?", "Enter name...")
// Show progress
coal.ShowProgress(ctx, "Processing", 100, func(update func(int)) {
// Your work here
for i := 0; i <= 100; i += 10 {
update(i)
}
})
// Display styled result
message := coal.NewTextDisplay().
SetText("Welcome, " + name + "!").
SetPrefix("Success: ").
SetStyle(coal.NewStyle().Foreground(coal.ColorGreen))
fmt.Print(message.Render(ctx))
}That's it. No complex setup, no event loop management, no manual rendering. Just create components and they work.
Building terminal UIs in Go is typically complex. You need to:
- Handle raw terminal input/output
- Manage screen rendering and updates
- Implement component state management
- Deal with terminal size changes
- Handle concurrent user interactions
Coal handles all of this with a simple component-based API:
| Without Coal | With Coal |
// Setup raw terminal mode
oldState, _ := term.MakeRaw(int(os.Stdin.Fd()))
defer term.Restore(int(os.Stdin.Fd()), oldState)
// Clear screen
fmt.Print("\033[2J\033[H")
// Draw input box manually
fmt.Print("┌─────────────────┐\n")
fmt.Print("│ Enter name: │\n")
fmt.Print("│ │\n")
fmt.Print("└─────────────────┘\n")
// Handle input character by character
var input string
for {
var b [1]byte
os.Stdin.Read(b[:])
if b[0] == 13 { // Enter
break
}
if b[0] == 127 { // Backspace
if len(input) > 0 {
input = input[:len(input)-1]
// Redraw everything...
}
continue
}
input += string(b[0])
// Redraw everything...
} |
name, err := coal.Input(ctx,
"What's your name?",
"Enter name...")
// That's it! Full editing support included |
go get github.com/voocel/coal@latestPerfect for LLM integrations with built-in streaming support:
// Real-time AI response streaming
stream := coal.NewAIRealTimeStream()
stream.Start()
// As each token arrives from your LLM API
for token := range llmTokens {
stream.Append(token) // Immediately displayed
}
stream.Complete()Works with any streaming API:
// OpenAI streaming example
stream := coal.NewAIRealTimeStream()
stream.Start()
resp, _ := client.CreateChatCompletionStream(ctx, req)
for {
response, err := resp.Recv()
if err == io.EOF {
break
}
stream.Append(response.Choices[0].Delta.Content)
}
stream.Complete()// Text input with validation
input := coal.NewTextInput().
SetMessage("Enter email:").
SetPlaceholder("user@example.com").
SetValidator(validateEmail).
SetWidth(50)
// Password input
password := coal.NewPasswordInput().
SetMessage("Password:").
SetShowPassword(false)
// Multi-line text area
textarea := coal.NewTextArea().
SetMessage("Description:").
SetSize(60, 8).
SetLineNumbers(true)// Single selection
options := []coal.Option[string]{
{Value: "go", Label: "Go", Hint: "Fast and reliable"},
{Value: "rust", Label: "Rust", Hint: "Memory safe"},
}
selected, _ := coal.SelectOption(ctx, "Choose language:", options)
// Multi-selection
tools, _ := coal.MultiSelectOptions(ctx, "Select tools:", toolOptions)// Progress bar
coal.ShowProgress(ctx, "Processing files", 100, func(update func(int)) {
// Your work here
})
// Spinner
coal.ShowSpinner(ctx, "Loading data", func() {
// Your work here
})
// Task sequence
tasks := []coal.Task{
{"Initialize", func() { /* work */ }},
{"Process", func() { /* work */ }},
{"Complete", func() { /* work */ }},
}
coal.RunTaskSequence(ctx, tasks)// Container with border
container := coal.NewContainer().
SetTitle("User Profile").
SetBorder(true).
SetRounded(true).
AddChild(userInfo).
AddChild(statusDisplay)
// Vertical stack
vstack := coal.NewVStack().
SetSpacing(1).
AddChild(header).
AddChild(content).
AddChild(footer)
// Split layout
split := coal.NewSplit().
SetLeft(sidebar).
SetRight(mainContent).
SetRatio(0.3)Built-in themes with full customization:
// Built-in themes
coal.ThemeDefault
coal.ThemeModern
coal.ThemeGitHub
coal.ThemeVSCode
coal.ThemeDracula
// Custom styling
style := coal.NewStyle().
Foreground(coal.ColorBlue).
Background(coal.ColorYellow).
SetBold(true)
text := coal.NewTextDisplay().
SetText("Custom styled text").
SetStyle(style)Coal uses an event-driven architecture with high-performance rendering:
- 60fps differential rendering - Only updates what changed
- Thread-safe components - Safe for concurrent use
- Memory optimized - Object pooling and buffer reuse
- Context-aware - Full context.Context support for cancellation
Components → Render Engine → Terminal I/O
↑ ↑ ↓
└── Event System ←───────────┘
- Go 1.24 or later
- Real terminal environment (Terminal.app, Command Prompt, SSH, etc.)
- Not supported: IDE output panels, non-interactive environments
func main() {
ctx := context.Background()
display := coal.NewTextDisplay().
SetText("Server status: Running").
SetPrefix("Status: ").
SetStyle(coal.NewStyle().Foreground(coal.ColorGreen))
fmt.Print(display.Render(ctx))
}func collectUserInfo(ctx context.Context) {
name, _ := coal.Input(ctx, "Name:", "Enter your name")
languages := []coal.Option[string]{
{Value: "go", Label: "Go"},
{Value: "python", Label: "Python"},
{Value: "rust", Label: "Rust"},
}
lang, _ := coal.SelectOption(ctx, "Favorite language:", languages)
// Process results...
}func chatInterface() {
// User input
userMsg := coal.NewUserMessage("How does this work?")
fmt.Print(userMsg.Render(ctx))
// AI streaming response
aiStream := coal.NewAIRealTimeStream()
aiStream.Start()
// Stream from your LLM API
for token := range llmResponse {
aiStream.Append(token)
}
aiStream.Complete()
}Optimized for complex terminal applications:
- < 1ms render time for typical components
- < 5MB memory usage for complex UIs
- 1000+ components supported in single application
- 60fps smooth animations and real-time updates
Coal is designed for modern terminal applications:
- CLI tools and utilities
- Development environments
- AI assistants and chat interfaces
- Monitoring dashboards
- Interactive installers
We welcome contributions! See our Contributing Guide for details.
git clone https://github.com/voocel/coal.git
cd coal
go mod tidy
go test ./...
# Run examples
go run examples/basic/main.goMIT License - see LICENSE for details.
Built with Go for the modern terminal. Inspired by Clack and Bubble Tea.