A modular, shell-based statusline for Claude Code CLI that displays real-time development information including context usage, rate limits, costs, git status, and more.
Barista is a Bash shell script project (Bash 3.2+ compatible for macOS). It generates a customizable status line that Claude Code displays at the bottom of the terminal. The architecture is modular - each piece of information (git, battery, CPU, etc.) is handled by a separate module in the modules/ directory.
Barista/
├── barista.sh # Main entry point - loads config, modules, orchestrates output
├── barista.conf # Default configuration file
├── install.sh # Interactive installer with arrow key navigation
├── VERSION # Version tracking (semver)
├── modules/
│ ├── utils.sh # Shared utility functions (MUST load first)
│ ├── directory.sh # Current directory module
│ ├── context.sh # Context window usage with progress bar
│ ├── git.sh # Git branch and status
│ ├── project.sh # Project type detection (Node, Rust, Python, etc.)
│ ├── model.sh # Current Claude model info
│ ├── cost.sh # Session cost and burn rate
│ ├── rate-limits.sh # 5-hour and 7-day rate limit tracking
│ ├── time.sh # Date and time display
│ ├── battery.sh # Battery percentage (macOS)
│ ├── cpu.sh # CPU usage
│ ├── memory.sh # RAM usage
│ ├── disk.sh # Disk space
│ ├── network.sh # Network info
│ ├── node.sh # Node.js version
│ ├── docker.sh # Docker container status
│ ├── weather.sh # Weather via wttr.in
│ └── ... # Additional modules
└── README.md
- Claude Code calls
barista.shwith JSON input containing workspace info, model, context window data, etc. - Configuration is loaded in order of precedence:
- Built-in defaults in
barista.sh barista.confin script directory$CLAUDE_CONFIG_DIR/barista.conf(user overrides, defaults to~/.claude/).barista.confin current project directory (per-project overrides)
- Built-in defaults in
- Modules are loaded from
modules/directory (utils.shfirst, then all others) - Modules are executed in the order specified by
MODULE_ORDERconfig - Output is concatenated with the configured
SEPARATORand printed
- Resolves
CLAUDE_CONFIG_DIR(env var or defaults to$HOME/.claude) - Defines default configuration values
- Loads configuration files in precedence order
- Loads all module files from
modules/ - Contains module registry mapping names to functions
- Executes enabled modules and joins output with separator
- Adjusts separator spacing based on
DISPLAY_MODE
- Theme system:
apply_theme()sets icons and indicators based onCOLOR_THEME - Cache system: File-based caching for expensive operations
- Safe number handling:
safe_int(),safe_divide(),safe_percent() - Status indicators:
get_status()(3-level),get_status_4level()(4-level for rate limits) - Icon handling:
get_icon()respectsUSE_ICONSsetting - Progress bar:
progress_bar()generates visual bars - JSON helpers:
json_get(),json_get_int()for safe extraction - Display mode checks:
is_compact(),is_verbose() - Logging:
log_debug()for debug mode
All settings are documented with comments. Key settings:
SEPARATOR- Character(s) between modules (default:" | ")DISPLAY_MODE-"normal","compact", or"verbose"COLOR_THEME-"default","minimal","vibrant","monochrome", or"nerd"USE_ICONS- Enable/disable emoji iconsSTATUS_STYLE-"emoji","ascii", or"dots"MODULE_*- Enable/disable individual modulesMODULE_ORDER- Comma-separated list defining display order
The COLOR_THEME setting changes status indicators and icons globally:
| Theme | Status Indicators | Icon Style | Use Case |
|---|---|---|---|
| default | 🟢 🟡 🟠 🔴 | Standard emoji (📁 📊 🌿) | General use |
| minimal | ◦ ◦ ◦ ● | Geometric (→ ◐ ⎇ ◈) | Clean, subtle look |
| vibrant | 💚 💛 🧡 ❤️ | Expressive (📂 🎯 🔀 🧠) | High visibility |
| monochrome | [OK] [~~] [!!] [XX] | ASCII text (DIR: CTX: GIT:) | Terminal compatibility |
| nerd | Nerd Font glyphs | Requires Nerd Font |
Themes are applied via apply_theme() in utils.sh after all configs are loaded.
Each module follows this pattern:
# =============================================================================
# Module Name - Brief description
# =============================================================================
# Configuration options:
# OPTION_NAME - Description (default: value)
# =============================================================================
module_name() {
local input="$1" # JSON input (for modules that need it)
# Get configuration with defaults
local icon=$(get_icon "${MODULE_ICON:-📊}" "FALLBACK:")
local some_option="${SOME_OPTION:-default}"
# Do work...
# Build and output result
local result="$icon some_value"
echo "$result"
}- Input-dependent modules (context, model, cost): Receive JSON input as
$1 - Directory-dependent modules (git, project): Receive current directory as
$1 - Standalone modules (time, battery, cpu): Take no arguments
The DISPLAY_MODE setting affects multiple behaviors:
normal: Balanced display with icons and key info, padded separators, spaces before status indicatorscompact: Minimal display, no separator padding, no spaces before status indicatorsverbose: Full display with all available information
Two systems for visual status:
- 3-level (
get_status): green/yellow/red based on warning/critical thresholds - 4-level (
get_status_4level): green/yellow/orange/red for more granular rate limit display
Both respect DISPLAY_MODE for spacing and STATUS_STYLE for appearance (emoji/ascii/dots).
- Create
modules/mymodule.shfollowing the pattern above - Add to module registry in
barista.sh:case "$module_name" in mymodule) echo "module_mymodule" ;;
- Add to
run_module()case if it needs special arguments - Add configuration defaults to
barista.shandbarista.conf:MODULE_MYMODULE="false" # Disabled by default
- Add to
MODULE_ORDERwhere you want it to appear
- Bash 3.2+ compatible - No associative arrays, use
casestatements instead - Use utility functions -
safe_int(),json_get(), etc. for safe operations - Local variables - Always declare with
localin functions - Quoting - Always quote variables:
"$var"not$var - Configuration pattern:
local value="${CONFIG_VAR:-default}" - Error handling - Redirect stderr:
command 2>/dev/null - Comments - Document configuration options at module top
Test the statusline manually:
echo '{"workspace":{"current_dir":"'$PWD'"},"model":{"display_name":"Test"},"output_style":{"name":"default"},"context_window":{"context_window_size":200000,"current_usage":{"input_tokens":10000}}}' | ./barista.shEnable debug mode:
DEBUG_MODE="true" # In config
# Logs to $CLAUDE_CONFIG_DIR/barista.log- Required:
jq(JSON processor),bc(calculator) - macOS specific:
security(keychain access for OAuth tokens) - Optional: Various CLI tools for specific modules (docker, node, etc.)
Barista respects the CLAUDE_CONFIG_DIR environment variable for users who have moved their Claude configuration from the default ~/.claude/. This is resolved once in barista.sh and inherited by all modules:
CLAUDE_CONFIG_DIR="${CLAUDE_CONFIG_DIR:-$HOME/.claude}"Files stored in this directory:
barista.conf- User config overridesbarista-cache/- Cache for expensive operations (weather, network, etc.)barista.log- Debug log (whenDEBUG_MODE="true").usage_history- Rate limit history for projections
Modules also include their own ${CLAUDE_CONFIG_DIR:-$HOME/.claude} fallback for robustness if sourced independently.
The rate limits module (rate-limits.sh) is the most complex:
- Fetches usage from Anthropic API using OAuth token from macOS Keychain
- Caches responses to avoid excessive API calls
- Maintains history file for projection calculations
- Implements file size caps to prevent memory issues
- Shows 4-level color indicators for usage thresholds
The installer (install.sh) provides:
- Interactive module selection with arrow key navigation
- Live preview of statusline
- Multiple presets (minimal, developer, etc.)
- Auto-update checking from GitHub
- Backup/restore of previous statusline