π Tap
Tap is a Go port of the popular TypeScript Clack library for building beautiful, interactive command-line applications.
β οΈ Heavy Development: This project is currently in heavy development. APIs may change, and some features are still being implemented. Use with caution in production environments.
π― About
Clack is a library that makes building interactive command-line applications effortless with beautiful, minimal, and opinionated CLI prompts. Tap brings this elegant experience to the Go ecosystem while maintaining the same design philosophy and user experience.
β
What's Ported
Core Functionality
- β
Event-driven prompt system - Complete with proper state management and event loop architecture
- β
Terminal management - Raw terminal mode, keyboard input handling, and cursor control
- β
Mock testing utilities - Full test coverage with mock input/output for reliable testing
Prompts (Unstyled - Core Package)
- β
Text Input - Single-line text input with cursor navigation, validation, and default values
- β
Confirm - Yes/No prompts with keyboard navigation
- β
Select - Single selection from a list with cursor navigation and wrap-around
Prompts (Styled - Prompts Package)
- β
Text Input - Beautifully styled text prompts with symbols, bars, placeholders, and error states
- β
Confirm - Styled confirmation prompts with radio button interface
- β
Select - Styled selection prompts with radio buttons, hints, and color-coded options
- β
Progress Bar - Animated progress with messages and final states
- β
Box - Styled message boxes with rounded/square borders, alignment, and auto-wrapping
- β
Symbols & Styling - Unicode symbols, ANSI colors, and consistent visual design
Still To Come
- π Password Input - Masked text input
- π Multi-Select - Multiple selection from a list
- π Autocomplete - Text input with autocomplete suggestions
- π Spinner - Loading indicators for long-running operations
- π Group - Grouped prompts for complex workflows
- π Note/Log - Informational messages and logging utilities
π Quick Start
Installation
go get github.com/yarlson/tap
Basic Usage
package main
import (
"fmt"
"github.com/yarlson/tap/prompts"
"github.com/yarlson/tap/terminal"
)
func main() {
// Initialize terminal
term, err := terminal.New()
if err != nil {
panic(err)
}
defer term.Close()
// Text input
name := prompts.Text(prompts.TextOptions{
Message: "What's your name?",
Input: term.Reader,
Output: term.Writer,
})
// Confirmation
confirmed := prompts.Confirm(prompts.ConfirmOptions{
Message: fmt.Sprintf("Hello %s! Continue?", name),
Input: term.Reader,
Output: term.Writer,
})
if confirmed.(bool) {
fmt.Println("Let's go! π")
}
}
Advanced Features
// Text with validation and default value
email := prompts.Text(prompts.TextOptions{
Message: "Enter your email:",
Placeholder: "user@example.com",
DefaultValue: "anonymous@example.com",
Validate: func(input string) error {
if !strings.Contains(input, "@") {
return errors.New("Please enter a valid email")
}
return nil
},
Input: term.Reader,
Output: term.Writer,
})
// Confirmation with custom labels
proceed := prompts.Confirm(prompts.ConfirmOptions{
Message: "Deploy to production?",
Active: "Deploy",
Inactive: "Cancel",
InitialValue: false,
Input: term.Reader,
Output: term.Writer,
})
Progress Bar
// Progress bar with animated frames and messages
prog := prompts.NewProgress(prompts.ProgressOptions{
Style: "heavy", // "light", "heavy", or "block"
Max: 100, // total units of work
Size: 40, // bar width in characters
Output: term.Writer, // implements prompts.Writer
})
prog.Start("Processing...")
// Update progress and optionally the message
for i := 0; i <= 100; i += 10 {
time.Sleep(200 * time.Millisecond)
prog.Advance(10, fmt.Sprintf("Processing... %d%%", i))
}
// Stop with final status. code: 0=success, 1=cancel, other=error
prog.Stop("Done!", 0)
ποΈ Architecture
Tap follows a clean, event-driven architecture:
core - Core prompt engine with unstyled, functional prompts
prompts - Beautifully styled prompts built on top of core
terminal - Terminal management and keyboard input handling
Event Loop Design
Tap uses a pure event loop architecture (no mutexes or atomic operations) for excellent performance and race-condition-free operation:
// Events flow through a single event loop
for event := range prompt.events {
event(&state) // Update state
prompt.render(&state) // Render changes
prompt.updateSnapshot(&state) // Update atomic snapshot
}
π§ͺ Testing
All prompts include comprehensive test coverage with mock input/output:
# Run all tests
go test ./...
# Run with race detection
go test -race ./...
# Run specific package tests
go test ./prompts -v
π Project Structure
go/
βββ README.md
βββ go.mod
βββ go.sum
βββ LICENSE
βββ examples/
β βββ confirm/
β β βββ main.go
β βββ multiple/
β β βββ demo.tape
β β βββ main.go
β βββ progress/
β β βββ main.go
β βββ select/
β β βββ main.go
β βββ text/
β βββ main.go
βββ core/ # Core prompt engine (unstyled)
β βββ confirm.go
β βββ confirm_test.go
β βββ mock.go
β βββ prompt.go
β βββ prompt_test.go
β βββ select.go
β βββ select_test.go
β βββ text.go
β βββ text_test.go
β βββ types.go
βββ prompts/ # Styled prompts and primitives
β βββ box.go
β βββ box_test.go
β βββ confirm.go
β βββ confirm_test.go
β βββ messages.go
β βββ messages_test.go
β βββ progress.go
β βββ progress_test.go
β βββ select.go
β βββ select_test.go
β βββ symbols.go
β βββ text.go
β βββ text_test.go
β βββ types.go
βββ terminal/
βββ terminal.go
π€ Contributing
We welcome contributions! This project is in active development and there's lots to build.
Development Setup
# Clone the repository
git clone https://github.com/yarlson/tap.git
cd tap
# Run tests
go test ./...
# Try examples
go run examples/text/main.go
go run examples/confirm/main.go
go run examples/select/main.go
go run examples/progress/main.go
go run examples/multiple/main.go
What Needs Help
- New Prompt Types: Multi-Select, Password, Autocomplete
- Enhanced Styling: Better color support, themes, custom symbols
- Documentation: More examples, API documentation, tutorials
- Testing: Edge cases, cross-platform testing, performance tests
- Bug Fixes: Race conditions, rendering issues, keyboard handling
Coding Standards
- Follow Go best practices and
gofmt formatting
- Maintain test coverage above 80%
- Use event-driven architecture (no mutexes/atomics)
- Write clear, self-documenting code
- Add examples for new features
π License
MIT License - see LICENSE file for details.
π Acknowledgments
- Clack - The original TypeScript library that inspired this project
- @eiannone/keyboard - Cross-platform keyboard input for Go
- The Go community for excellent tooling and libraries
π Links
Made with β€οΈ for the Go community. Building interactive CLIs shouldn't be so hard!