Skip to main content

Overview

The bash generator creates self-contained, optimized bash scripts that display statusline information in Claude Code terminals. The generation system is template-based with conditional sections determined by user configuration.

Generator Architecture

Main Generator Function

The core generator function is generateBashStatusline() in src/generators/bash-generator.ts:
export function generateBashStatusline(config: StatuslineConfig): string {
  const hasGit = config.features.includes('git')
  const hasUsage = config.features.some(f => 
    ['usage', 'session', 'tokens', 'burnrate'].includes(f)
  )
  const hasDirectory = config.features.includes('directory')
  const hasModel = config.features.includes('model')
  const hasContext = config.features.includes('context')

  // Build usage feature config
  const usageConfig = {
    enabled: hasUsage && config.ccusageIntegration,
    showCost: config.features.includes('usage'),
    showTokens: config.features.includes('tokens'),
    showBurnRate: config.features.includes('burnrate'),
    showSession: config.features.includes('session'),
    showProgressBar: config.theme !== 'minimal'
  }

  // Generate script with conditional sections
  const script = `#!/bin/bash
# Generated by cc-statusline v${VERSION}
input=$(cat)
${config.logging ? generateLoggingCode() : ''}
${generateColorBashCode({ enabled: config.colors, theme: config.theme })}
${hasGit ? generateGitBashCode(gitConfig, config.colors) : ''}
${hasUsage ? generateUsageBashCode(usageConfig, config.colors) : ''}
${generateDisplaySection(config, gitConfig, usageConfig)}
`

  return script.replace(/\n\n\n+/g, '\n\n').trim() + '\n'
}

Feature Flag System

Feature flags control which bash code blocks are included:
const hasGit = config.features.includes('git')
const hasUsage = config.features.some(f => 
  ['usage', 'session', 'tokens', 'burnrate'].includes(f)
)
const hasDirectory = config.features.includes('directory')
const hasModel = config.features.includes('model')
const hasContext = config.features.includes('context')
Only enabled features generate corresponding bash code, keeping scripts minimal.

Script Structure

Generated Script Anatomy

#!/bin/bash
# Header: Version, timestamp, configuration
STATUSLINE_VERSION="1.4.0"

input=$(cat)  # Read JSON input from stdin

# Check jq availability
HAS_JQ=0
if command -v jq >/dev/null 2>&1; then
  HAS_JQ=1
fi

# Optional: Logging code
# Color definitions
# Utility functions
# Feature-specific code (git, usage, context)
# Display section

Header Generation

Every script includes metadata:
const timestamp = new Date().toISOString()
const script = `#!/bin/bash
# Generated by cc-statusline v${VERSION} (https://www.npmjs.com/package/@chongdashu/cc-statusline)
# Custom Claude Code statusline - Created: ${timestamp}
# Theme: ${config.theme} | Colors: ${config.colors} | Features: ${config.features.join(', ')}
STATUSLINE_VERSION="${VERSION}"

JSON Parsing System

jq vs Fallback Parser

Scripts include two JSON parsing strategies:
if [ "$HAS_JQ" -eq 1 ]; then
  current_dir=$(echo "$input" | jq -r '.workspace.current_dir // .cwd // "unknown"' 2>/dev/null | sed "s|^$HOME|~|g")
  model_name=$(echo "$input" | jq -r '.model.display_name // "Claude"' 2>/dev/null)
fi

JSON Extractor Function

The fallback parser uses a reusable utility function (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/')
  
  # Convert escaped backslashes to forward slashes for Windows paths
  if [ -n "$value" ]; then
    value=$(echo "$value" | sed 's/\\\\\\/\//g')
  fi
  
  # If no string value found, try to extract number value (unquoted)
  if [ -z "$value" ] || [ "$value" = "null" ]; then
    value=$(echo "$json" | grep -o "\\"\${field}\\"[[:space:]]*:[[:space:]]*[0-9.]+" | head -1 | sed 's/.*:[[:space:]]*\([0-9.]+\).*/\1/')
  fi
  
  # Return value or default
  if [ -n "$value" ] && [ "$value" != "null" ]; then
    echo "$value"
  else
    echo "$default"
  fi
}

Quote Escaping

The Critical Bug-Prone Area

Lines 100-105 in bash-generator.ts contain grep patterns requiring double escaping. This is the most error-prone part of the codebase.

Escaping Rules

TypeScript Template Literal: Needs \\ for a single backslash Bash Script: Needs \" for escaped quotes Combined: \\"\\${field}\\" produces "${field}" in the final bash script

Example

// In bash-generator.ts
local value=$(echo "$json" | grep -o "\\"\\ ${field}\\"[[:space:]]*:[[:space:]]*\\"[^\\"]*\\"" | head -1)

Feature Generators

Git Code Generation

From src/features/git.ts:
export function generateGitBashCode(config: GitConfig, colors: boolean): string {
  return `
# ---- git information ----
git_branch=""
if command -v git >/dev/null 2>&1 && git rev-parse --git-dir >/dev/null 2>&1; then
  git_branch=$(git symbolic-ref --short HEAD 2>/dev/null || git rev-parse --short HEAD 2>/dev/null)
fi
${colors ? `git_color() { printf '\\033[38;5;158m'; }  # mint green` : ''}
`
}

Usage Code Generation

From src/features/usage.ts:
export function generateUsageBashCode(config: UsageConfig, colors: boolean): string {
  if (!config.enabled) return ''
  
  return `
# ---- usage tracking via ccusage ----
${config.showCost ? `cost_usd=""` : ''}
${config.showTokens ? `tot_tokens=""` : ''}
${config.showBurnRate ? `
cost_per_hour=""
tpm=""
` : ''}

# Execute ccusage with locking mechanism
if command -v npx >/dev/null 2>&1; then
  # [Lock-based ccusage execution code]
fi
${colors ? generateUsageColors() : ''}
`
}

Display Section Generation

The display section creates the final output (src/generators/bash-generator.ts:214-293):
function generateDisplaySection(config: StatuslineConfig, gitConfig: any, usageConfig: any): string {
  return `
# ---- render statusline ----
# Line 1: Core info (directory, git, model, claude code version, output style)
${config.features.includes('directory') ? `printf '📁 %s%s%s' "$(dir_color)" "$current_dir" "$(rst)"` : ''}${gitConfig.enabled ? `
if [ -n "$git_branch" ]; then
  printf '  🌿 %s%s%s' "$(git_color)" "$git_branch" "$(rst)"
fi` : ''}

# Line 2: Context and session time
line2=""${config.features.includes('context') ? `
if [ -n "$context_pct" ]; then
  context_bar=$(progress_bar "$context_remaining_pct" 10)
  line2="🧠 $(context_color)Context Remaining: \${context_pct} [\${context_bar}]$(rst)"
fi` : ''}

# Print lines
if [ -n "$line2" ]; then
  printf '\\n%s' "$line2"
fi
printf '\\n'
`
}

Optimization Techniques

Template Cleanup

Remove excessive blank lines:
return script.replace(/\n\n\n+/g, '\n\n').trim() + '\n'

Conditional Code Blocks

Only generate code for enabled features:
${hasGit ? generateGitBashCode(gitConfig, config.colors) : ''}
${hasUsage ? generateUsageBashCode(usageConfig, config.colors) : ''}

POSIX Compliance

Generated scripts work with sh, bash, and zsh:
  • Avoid bash-specific features when possible
  • Use portable command syntax
  • Provide fallbacks for bash-only features

Testing Generated Scripts

Preview Command

Test scripts before installation:
cc-statusline preview .claude/statusline.sh
The preview command:
  1. Loads the generated script
  2. Pipes mock JSON data to it
  3. Captures and displays output
  4. Reports performance metrics

Mock Data Generation

From src/utils/tester.ts:
const mockInput = {
  workspace: { current_dir: process.cwd() },
  model: { display_name: "Claude Sonnet", version: "4" },
  session_id: "test-session",
  version: "1.0.85",
  output_style: { name: "default" },
  context_window: {
    context_window_size: 200000,
    current_usage: { input_tokens: 25000 }
  }
}

Next Steps

Architecture

Learn about project architecture

Contributing

Start contributing to the project

Build docs developers (and LLMs) love