Skip to main content

Project Overview

cc-statusline is a TypeScript CLI tool that generates custom statuslines for Claude Code. It creates optimized bash scripts that display directory, git info, model name, usage costs, and session time in the terminal.

Architecture Overview

The codebase follows a modular ESM TypeScript architecture with four distinct layers:

CLI Layer (src/cli/)

Purpose: User interaction and command handling
  • Commander.js-based CLI interface
  • Interactive prompts using Inquirer
  • Command registration and argument parsing
  • User preference collection
Key Files:
  • commands.ts - CLI command definitions
  • prompts.ts - Interactive configuration prompts

Generator Layer (src/generators/)

Purpose: Bash script generation based on user configuration
  • Template-based bash code generation
  • Feature flag-driven conditional sections
  • Optimized output with only selected features
  • POSIX-compliant script generation
Key Files:
  • bash-generator.ts - Main bash script generator (src/generators/bash-generator.ts:9)

Feature Modules (src/features/)

Purpose: Isolated implementations for specific statusline features
  • Git: Branch detection and status display
  • Usage Tracking: Cost and token statistics via ccusage
  • Colors: 256-color palette support for terminals
Design Pattern: Each feature is self-contained with graceful fallbacks when dependencies are unavailable.

Utility Layer (src/utils/)

Purpose: Supporting functionality for installation and testing
  • Installation utilities
  • Validation helpers
  • Mock testing support

Key Design Patterns

Feature Flags

Feature flags determine which bash code blocks are included in generated scripts:
const hasGit = config.features.includes('git')
const hasUsage = config.features.some(f => 
  ['usage', 'session', 'tokens', 'burnrate'].includes(f)
)
Only selected features generate corresponding bash code, keeping scripts minimal and fast.

Template-Based Generation

All bash generation uses TypeScript template strings with conditional sections:
export function generateBashStatusline(config: StatuslineConfig): string {
  const script = `#!/bin/bash
# Generated by cc-statusline v${VERSION}
${config.logging ? generateLoggingCode() : ''}
${generateColorBashCode({ enabled: config.colors, theme: config.theme })}
${hasGit ? generateGitBashCode(gitConfig, config.colors) : ''}
${hasUsage ? generateUsageBashCode(usageConfig, config.colors) : ''}
`
  return script.replace(/\n\n\n+/g, '\n\n').trim() + '\n'
}

Mock Testing

The preview command simulates Claude Code’s JSON input for testing:
  • Generates realistic mock data
  • Tests statusline output before installation
  • Validates performance metrics
  • No Claude Code instance required

Build System

Technology: tsup for ESM bundling Configuration:
  • Target: Node 16+
  • Module format: ESM
  • Automatic shebang insertion (#!/usr/bin/env node)
  • Source maps for debugging
Build Commands:
npm run build     # Production build
npm run dev       # Watch mode for development

Generated Scripts

Characteristics

  • Self-contained: No external dependencies required
  • Fast: Execute in <100ms with minimal resource usage
  • Graceful fallbacks: Work without jq, git, or ccusage
  • POSIX-compliant: Compatible with sh, bash, zsh

Fallback Strategy

Scripts include multiple layers of fallbacks:
  1. JSON Parsing: jq → bash fallback parser
  2. Git Integration: git command → skip git features
  3. Usage Tracking: ccusage → skip usage features

Installation Flow

The installation process follows these steps:
  1. Collect Preferences: Interactive inquirer prompts for features, theme, colors
  2. Generate Script: Create optimized bash script with only selected features
  3. Write File: Save to .claude/statusline.sh with execute permissions
  4. Update Settings: Modify .claude/settings.json to register statusline command

Critical Implementation Details

JSON Parsing in Bash

The bash-generator.ts file contains a fallback JSON parser for systems without jq (src/generators/bash-generator.ts:88-121):
extract_json_string() {
  local json="$1"
  local key="$2"
  local default="${3:-}"
  
  # For nested keys like workspace.current_dir, get the last part
  local field="${key##*.}"
  field="${field%% *}"  # Remove any jq operators
  
  # Try to extract string value (quoted)
  local value=$(echo "$json" | grep -o "\\"\${field}\\"[[:space:]]*:[[:space:]]*\\"[^\\"]*\\"" | head -1 | sed 's/.*:[[:space:]]*"\([^"]*\)".*/\1/')
  
  # Return value or default
  if [ -n "$value" ] && [ "$value" != "null" ]; then
    echo "$value"
  else
    echo "$default"
  fi
}

Quote Escaping

Critical: Lines 100-105 in bash-generator.ts contain grep patterns requiring double escaping:
  • TypeScript template literal needs \\ for a single backslash
  • Bash needs \" for escaped quotes
  • Combined: \\"\\${field}\\" produces "${field}" in final bash script

Module System

ESM Conventions

  • Use ESM imports with .js extensions (even for .ts files)
  • No CommonJS require statements
  • Top-level await supported
Example:
import { StatuslineConfig } from '../cli/prompts.js'
import { generateColorBashCode } from '../features/colors.js'

Performance Characteristics

MetricTargetTypical
Execution Time<100ms45-80ms
Memory Usage<5MB~2MB
CPU ImpactNegligible<1%
DependenciesMinimaljq only
Benchmarked on macOS with all features enabled

Security Considerations

  • No network requests: Except ccusage integration via npx
  • Local file access: Only reads Claude Code JSON input
  • Secure defaults: Scripts execute with user permissions only
  • No data collection: Zero telemetry or analytics

Code Conventions

  • Indentation: 2 spaces
  • Semicolons: Not used (follows project style)
  • Typing: Strict TypeScript with explicit types
  • Commits: Conventional Commits format

Next Steps

Bash Generation

Learn how bash scripts are generated

Testing

Run tests and validate changes

Build docs developers (and LLMs) love