This is a submission for the GitHub Copilot CLI Challenge
Author: Cesar Castillo
Repository: https://github.com/CGCM070/copilot-usage_tui
From Invisible to Visible
Stop guessing. Start knowing.
GitHub Copilot Pro gives you 300 requests per monthβ¦ but having to go to the site, navigate through menus, and dig into a specific section just to check your usage? Thatβs tedious
I built a terminal-based TUI that transforms your Copilot usage from an invisible mystery into a beautiful, real-time dashboard. Because developers deserve to know exactly how they're using their AI pair programmer.
What I Built : Copilot-usage
A Rust-based CLI tool with an interactive terminal UI that tracks GitHub Copilot Pro usage in real-time, featuring progress bars, per-model statistics, and seamless Waybar integration for Hyprland users.
The Problem
If you're a GitHub Copilot Pro user, you know the drill:
You get 300 premium requests per month
There is a page where you can check usageβ¦
But you have to go to the site, open the right section, and dig through settings to find it
So youβre never quite sure where you stand until you manually go look
300 requests. Visibility β technically. Convenience? Not so much.
The Solution: Copilot Usage
I built a terminal dashboard that gives you complete visibility into your Copilot consumption with zero friction.
Key Features
π Beautiful Terminal Dashboard
- Real-time progress bars with color-coded zones (green β orange β red)
- Per-model usage breakdown (GPT-4, Claude 3.5, Gemini, etc.)
- Compact, density-focused layout inspired by
btop - 9 gorgeous color themes: Dark, Nord, Monokai, Gruvbox, Catppuccin, OneDark, TokyoNight, Solarized, Kanagawa
β‘ Async Architecture
- Non-blocking UI with tokio async runtime
- Smooth spinner animations during API calls (20 FPS)
- Cancelable operations with Escape key
- Background refresh while you keep working
π¨ Theme System
- Instant theme switching without exiting TUI
- Persistent theme configuration
- Consistent warning (orange) and error (red) colors across all themes
- Segmented progress bars for visual feedback
πΎ Smart Caching
- Local cache with 5-minute TTL (configurable)
- Cache status indicator (Fresh/Expired/Missing)
- Manual refresh with 'r' key
- Automatic cache invalidation on
--refreshflag
π§ Interactive Modals
- Command menu (press
/) for quick actions - Theme selector with live preview
- Help dialog with all keybindings (press
?) - Error dialogs with debug mode toggle (press
d) - Cache info modal showing last update time
π Waybar Integration
- JSON output for Waybar status bar
- Customizable format strings
- Shows percentage in your status bar
- Perfect for Hyprland/wayland users
π Zero-Config Setup
- Interactive first-run wizard
- Automatic GitHub username detection
- Fine-grained PAT or classic token support
- XDG-compliant config directory
Architecture Deep Dive
This isn't just a simple API wrapper. It's a full async TUI application with clean separation of concerns:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Terminal UI (ratatui) β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β UI Components β β
β β β’ Header (user info) β β
β β β’ Usage Progress Bar β β
β β β’ Model Usage Table β β
β β β’ Modal Dialogs β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Event Loop (50ms poll) β β
β β β’ Keyboard input handling β β
β β β’ Async result processing β β
β β β’ Spinner animation updates β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Async Handler (tokio) β β
β β β’ Background API calls β β
β β β’ Cache operations β β
β β β’ mpsc channels for results β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β GitHub API β
β β’ /users/{username}/settings/billing/... β
β β’ 5000 req/hour rate limit β
β β’ Fine-grained PAT with Plan (Read) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Async Event Loop Pattern
The heart of the application is a non-blocking event loop:
loop {
// 1. Handle user input (non-blocking)
if event::poll(Duration::from_millis(50))? {
// Process keyboard events
}
// 2. Animate spinner during loading
if matches!(app.state, LoadingRefresh | LoadingCache) {
app.advance_spinner();
}
// 3. Check for async results
if let Some(result) = async_handler.try_recv() {
match result {
RefreshComplete(Ok(stats)) => update_dashboard(stats),
RefreshComplete(Err(e)) => show_error_modal(e),
CacheInfoReady(info) => show_cache_modal(info),
}
}
// 4. Render UI (20 FPS)
terminal.draw(|f| render_ui(f, &app, &stats, theme))?;
}
Why async matters:
- API calls don't freeze the UI
- Spinner animations stay smooth
- Users can cancel operations anytime
- Background tasks complete even after cancel
Technical Decisions
1. Modular Component Architecture
Each UI component is a pure function with zero side effects:
// Pure rendering function - no state mutations
pub fn render_usage_overall(
f: &mut Frame,
area: Rect,
stats: &UsageStats,
colors: &ThemeColors
) {
// Calculate progress bar segments
// Render with theme colors
// No state changes, no events handled
}
Benefits:
- Easy to test (input β output)
- No hidden state mutations
- Components compose naturally
- Theme changes apply instantly
2. State Machine Pattern
AppState enum models all UI states explicitly:
pub enum AppState {
Dashboard, // Main view
LoadingRefresh, // Spinner during API call
ShowCacheInfo(CacheInfo), // Cache status modal
ShowError { // Error with debug toggle
message: String,
debug_message: String,
show_debug: bool,
},
// ... more states
}
No boolean flags. No hidden state. Every state is explicit and handled.
3. Constant Warning/Error Colors
Across all 9 themes, warning and error colors remain constant:
-
Warning:
rgb(255, 184, 108)(orange) -
Error:
rgb(255, 85, 85)(red)
Users instantly recognize status regardless of theme.
4. Compact Layout Philosophy
Inspired by system monitors like btop:
- Dynamic height: Model table resizes based on data (N + 3 rows)
- Compact width: 50% of terminal for readability
- Minimal padding: Information density over whitespace
- Rounded borders: Modern, polished feel
5. Never Exit TUI Philosophy
All operations happen via modals:
- Reconfigure token? Modal dialog
- Change theme? Theme selector modal
- Refresh data? Loading spinner modal
- Error occurred? Error modal with debug info
The TUI stays alive. No jarring exits. No lost context.
πΈ Screenshots
Dashboard - Before
Dashboard - After
Theme Selector
Waybar Integration
Refresh
My Experience with GitHub Copilot CLI
This project was built with extensive help from GitHub Copilot CLI, turning natural language into idiomatic Rust code.
How I Used Copilot CLI
1. Async Architecture Design
# Asked: "Best way to structure async TUI in Rust?"
# Copilot suggested: tokio + mpsc channels + non-blocking event loop
# Result: Smooth 20 FPS UI with background API calls
2. State Machine Pattern
# Asked: "How to model TUI states without boolean flags?"
# Copilot proposed: AppState enum with exhaustive match
# Result: Clean state transitions, no hidden bugs
3. Theme System
# Asked: "Implement 9 color themes with constant warning/error colors"
# Copilot generated: ThemeColors struct + theme implementations
# Result: 9 gorgeous themes with consistent UX
4. Progress Bar Segmentation
# Asked: "Create gradient progress bars (greenβorangeβred)"
# Copilot designed: Segmented bar with zone calculations
# Result: Visual feedback at a glance
5. Cache System
# Asked: "Implement file-based cache with TTL in Rust"
# Copilot built: Cache with CacheStatus enum (Fresh/Expired/Missing)
# Result: Fast cached responses, automatic invalidation
Copilot suggested the modular component pattern that made the codebase maintainable and testable.
Edge Cases: Error handling, terminal cleanup on panic, XDG directory resolution - Copilot handled these gracefully.
Installation ( Only tested on LINUX )
Using install script (Recommended)
git clone https://github.com/CGCM070/copilot-usage.git
cd copilot-usage/
./install.sh
Manual installation
cargo install --path . --force
Usage
# First run - interactive setup
copilot-usage
# Dashboard (uses cache if available)
copilot-usage
# Force refresh from API
copilot-usage --refresh
# Waybar JSON output
copilot-usage --waybar
# Change theme temporarily
copilot-usage --theme nord
# Reconfigure token/theme
copilot-usage reconfigure
# Check cache status
copilot-usage --cache-status
Keybindings (in TUI)
| Key | Action |
|---|---|
r |
Refresh data from API |
t |
Open theme selector |
? |
Show help dialog |
/ |
Open command menu |
c |
Show cache info |
q Esc
|
Quit / Close modal |
Configuration
File: ~/.config/copilot-usage/config.toml
token = "ghp_..."
theme = "dark"
cache_ttl_minutes = 5
waybar_format = "{}"
username = "octocat"
Required GitHub Permissions
-
Fine-grained PAT with
Plan (Read)permission - Classic tokens need
read:userscope - NOT "Copilot Requests" - different permission!
What's Next?
Notification Support - Alert when usage > 80%
Historical Graphs - Usage trends over time
π€ Open Source
This project is open source. Want to contribute?
- PRs welcome
- Good first issues: new themes, documentation, tests
Credits & Thanks
- GitHub for Copilot Pro - the AI that powers our coding
- GitHub Copilot CLI for helping build this tool faster than ever <3
- DEV.to for hosting this challenge





Top comments (9)
I loved the TUI. It's so clean and smooth!
Appreciate it, Rohan! Iβm going to keep refining it to match my style
that's cool!
Very clean and reliable. Great work!
Thanks a lot, Francis! I appreciate you taking the time to read it.
Nice outfit, looks great π₯
Thanks Nube, appreciate the comment! π
This is just so well detailed.
Thanks, Faith! Was there any specific part that you found most useful? Best regards!