A Terminal User Interface (TUI) for managing Google Cloud Pub/Sub resources, built with Go and BubbleTea.
- 🎯 Interactive Terminal UI - Full keyboard-driven interface with vim-style navigation
- 📋 Topic & Subscription Management - List, create, delete, and filter topics and subscriptions
- 📤 Message Publishing - Publish messages with JSON templates and variable substitution
- 📥 Real-time Message Subscription - Receive and view messages in real-time
- ✅ Message Acknowledgment - Manual or automatic message acknowledgment
- 🔍 Regex Filtering - Filter topics, subscriptions, and messages using regex patterns
- 📊 Activity Logging - View all operations with color-coded log levels
- 🎨 Beautiful UI - Modern styling with Lipgloss
- Go 1.20+
- Google Cloud SDK (gcloud CLI)
- GCP Project with Pub/Sub API enabled
- Authentication configured (see below)
git clone <repository-url>
cd pubsub-tui2
go build -o pubsub-tui
./pubsub-tuigo install github.com/yourusername/pubsub-tui@latestSet your project ID:
# Option 1: Environment variable
export GOOGLE_CLOUD_PROJECT=your-project-id
# Option 2: gcloud configuration
gcloud config set project your-project-id# Application Default Credentials (recommended)
gcloud auth application-default login
# Or use a service account
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account-key.jsongcloud services enable pubsub.googleapis.comYour user/service account needs these IAM roles:
roles/pubsub.editor(or individual permissions)
For local development and testing, you can use the Google Cloud Pub/Sub emulator instead of connecting to real GCP resources. The application automatically detects when the emulator is configured and adjusts its behavior accordingly (no GCP authentication required).
# Install the emulator component (one-time)
gcloud components install pubsub-emulator
# Start the emulator
gcloud beta emulators pubsub start --host-port=localhost:8085In a new terminal, set the required environment variables:
# Point to the emulator (required)
export PUBSUB_EMULATOR_HOST=localhost:8085
# Set a project ID (required - can be any string for the emulator)
export GOOGLE_CLOUD_PROJECT=local-projectOr use the helper command to get the environment variables:
$(gcloud beta emulators pubsub env-init)
export GOOGLE_CLOUD_PROJECT=local-project./pubsub-tuiThe application will display a message indicating it's connecting to the emulator.
- Topics and subscriptions created in the emulator are ephemeral and lost when the emulator stops
- No GCP credentials or permissions are required
- The emulator supports most Pub/Sub operations but may have some limitations compared to the real service
- Useful for testing message flows without incurring GCP costs
./pubsub-tuiThe application will verify your credentials and connect to your GCP project.
| Key | Action |
|---|---|
Tab |
Cycle focus between panels |
Shift+Tab |
Cycle focus backward |
1-4 |
Jump to panel (Topics/Subscriptions/Publisher/Subscriber) |
q or Ctrl+C |
Quit application |
? |
Show help |
| Key | Action |
|---|---|
↑/↓ or j/k |
Navigate list |
Enter |
Select topic (filters subscriptions, sets publish target) |
n |
Create new topic |
d |
Delete selected topic |
/ |
Filter by regex |
Esc |
Clear filter |
| Key | Action |
|---|---|
↑/↓ or j/k |
Navigate list |
Enter |
Start/stop subscription (receive messages) |
n |
Create new subscription |
d |
Delete selected subscription |
/ |
Filter by regex |
Esc |
Clear filter |
| Key | Action |
|---|---|
↑/↓ or j/k |
Navigate JSON files |
Enter |
Publish message to selected topic |
v |
Edit variables for substitution |
Variable Substitution:
- Use
${variableName}in JSON files - Set variables:
key1=value1 key2=value2 - Example:
With variables:
{ "user": "${user}", "environment": "${env}" }user=alice env=production
| Key | Action |
|---|---|
↑/↓ or j/k |
Navigate messages |
Enter |
View message details |
a |
Acknowledge selected message |
A |
Toggle auto-acknowledge mode |
/ |
Filter messages by regex |
Ctrl+d/Ctrl+u |
Scroll message detail view |
Place JSON files in the working directory where you run pubsub-tui. They will be automatically loaded in the Publisher panel.
Example (order-event.json):
{
"orderId": "${orderId}",
"userId": "${userId}",
"environment": "${env}",
"timestamp": "2024-01-15T10:30:00Z",
"items": [
{
"product": "Widget",
"quantity": 5
}
]
}Set variables in Publisher: orderId=12345 userId=user-001 env=production
This project uses The Elm Architecture (MVU) pattern via BubbleTea. New to TUI development? Start here:
| Document | Description | Audience |
|---|---|---|
| ARCHITECTURE_QUICK_START.md | Quick introduction with examples | New TUI developers |
| ARCHITECTURE_DIAGRAMS.md | Visual diagrams of data flow | Visual learners |
| ARCHITECTURE.md | Complete architecture deep dive | Experienced developers |
| REQUIREMENTS.md | Full requirements specification | Product/QA teams |
The application follows these principles:
- Model-View-Update (MVU): Functional architecture with unidirectional data flow
- Message Passing: Components communicate via messages, not direct calls
- Commands for Side Effects: All I/O operations wrapped in async commands
- Immutable State: State changes only in Update function
- Pure View Functions: Rendering has no side effects
Quick Example:
User presses Enter → KeyMsg → Update → Model changes → View renders
↓
(Returns Command)
↓
Async operation (API call)
↓
Result as Message
↓
Update handles result
See ARCHITECTURE_QUICK_START.md for a complete walkthrough.
pubsub-tui/
├── main.go # Application entry point
├── internal/
│ ├── app/ # Main application coordinator (MVU root)
│ │ ├── app.go # Model and initialization
│ │ ├── update.go # State transitions
│ │ └── view.go # Layout and rendering
│ ├── components/ # UI components (each follows MVU)
│ │ ├── topics/ # Topics panel
│ │ ├── subscriptions/ # Subscriptions panel
│ │ ├── publisher/ # Publisher panel
│ │ ├── subscriber/ # Subscriber panel
│ │ ├── activity/ # Activity log panel
│ │ └── common/ # Shared messages and styles
│ ├── pubsub/ # GCP Pub/Sub business logic
│ │ ├── client.go # Client wrapper
│ │ ├── topics.go # Topic operations
│ │ ├── subscriptions.go # Subscription operations
│ │ ├── publisher.go # Publishing logic
│ │ └── subscriber.go # Subscription streaming
│ └── utils/ # Utility functions
└── testdata/ # Sample message templates
- BubbleTea: TUI framework (MVU pattern)
- Bubbles: Pre-built TUI components
- Lipgloss: Terminal styling
- Google Cloud Go SDK: Pub/Sub client library
# Build and run
go run main.go
# With specific project
GOOGLE_CLOUD_PROJECT=my-project go run main.go
# Build for production
go build -ldflags="-s -w" -o pubsub-tui- Create
internal/components/mycomponent/ - Add
model.go,update.go,view.go - Follow MVU pattern (see existing components)
- Register in
app.Model - Handle messages in
app.Update - Render in
app.View
See ARCHITECTURE.md for detailed guidance.
The TUI uses alt-screen mode, so you can't use fmt.Println(). Options:
-
Activity Log: Show logs in UI
return m, func() tea.Msg { return common.Info("Debug message") }
-
Log to File:
f, _ := os.OpenFile("debug.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) fmt.Fprintf(f, "Debug: %#v\n", someValue)
-
Use Delve with a separate terminal
# Set project
export GOOGLE_CLOUD_PROJECT=your-project-id
# or
gcloud config set project your-project-id# Re-authenticate
gcloud auth application-default loginCheck your IAM permissions:
gcloud projects get-iam-policy your-project-id \
--flatten="bindings[].members" \
--filter="bindings.members:user:your-email@example.com"You need roles/pubsub.editor or equivalent permissions.
- Ensure terminal supports 256 colors
- Minimum terminal size: 80x24 (recommended: 120x30+)
- Try a different terminal emulator (iTerm2, Windows Terminal, etc.)
- Select a topic in the Topics panel (Panel 1)
- Press
3to jump to Publisher panel - Navigate to a JSON file
- Press
vto set variables (if using templates) - Press
Enterto publish - Check Activity Log for confirmation
- Select a topic in the Topics panel (Panel 1)
- Press
2to jump to Subscriptions panel - Select a subscription for that topic
- Press
Enterto start receiving - Press
4to jump to Subscriber panel - View incoming messages in real-time
- Press
ato acknowledge individual messages - Or press
Ato toggle auto-acknowledge
- Press
1to jump to Topics panel - Press
n(new) - Enter topic name:
my-new-topic - Press
2to jump to Subscriptions panel - Select the new topic first (so it's the target)
- Press
n(new) - Enter subscription name:
my-new-subscription - The subscription is now linked to the topic
Contributions welcome! Please:
- Read ARCHITECTURE.md to understand the design
- Follow the MVU pattern for new components
- Add tests for business logic
- Keep UI components separate from business logic
- Use message passing for component communication
MIT License - see LICENSE file for details
- Charm for the excellent TUI frameworks
- Google Cloud for the Pub/Sub service
- The Go community for amazing tools and libraries
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Documentation: See docs/ folder
Happy Terminal UI-ing! 🚀
