Skip to content

Feature Request: More Widget Ideas #55

Open

Description

@coygeek

Hello,

See my 2 posts below for ideas for new widgets, based on:

  1. my own statusline github project
  2. ryoppippi/ccusage

Something to consider.

Cheers!

Activity

  1. coygeek commented on Aug 27, 2025

    @coygeek
    Author

    Title: Feature Request: Add Advanced Contextual Widgets for Deeper Claude Code Integration

    Body:

    Hi @sirmalloc,

    First off, fantastic work on ccstatusline! It's an incredibly polished and powerful tool. I was working on my own statusline implementation in Bash and TypeScript (2025-08-09-statusline) before I discovered your project, and yours is definitely the superior approach with its TUI and robust widget system.

    After comparing the two projects and reviewing the official Claude Code documentation, I've identified several features from my implementation that could be valuable additions to ccstatusline as new, optional widgets. These features focus on providing deeper, real-time insights into Claude Code's internal state, which can be invaluable for debugging and understanding the agent's behavior.

    I'd like to propose the following new widgets:


    1. Active Tool Widget

    Motivation:
    Provides immediate feedback on what tool Claude is currently executing (e.g., Bash, Edit, WebSearch). This is extremely helpful for long-running operations, as it confirms the agent is working on the right task without needing to switch to transcript mode (Ctrl+R). My implementation also tracked the tool's lifecycle (running, success, failure) and duration.

    Implementation Idea:
    My Bash implementation (.claude/hooks/activity_hook.sh) worked by writing the tool's state to a temporary file (/tmp/claude_tool_state_${SESSION_ID}.json) which the statusline would then read. The Claude Code documentation confirms that hooks can be used to track PreToolUse and PostToolUse, which is the ideal mechanism for this. A TypeScript implementation could monitor for these hook-generated state files.

    Display Example:

    • Running: ⚡ Bash (running 5s)
    • Success: ✅ Bash (success)
    • Failure: ❌ Bash (failure)

    2. Active Sub-Agent Widget

    Motivation:
    Claude Code's sub-agent feature is powerful but can be opaque. This widget would show which sub-agent is currently active (e.g., code-reviewer, debugger). This provides clarity on which "specialist" is handling the current task and why the agent's behavior might suddenly seem different.

    Implementation Idea:
    My agent_collector.sh tracked this state. The official documentation (en/docs/claude-code/sub-agents) confirms that sub-agents operate in their own context. The statusline JSON input includes a subagent_type field, making this directly accessible.

    Display Example:

    • 🤖 (Reviewer)
    • 🐛 (Debugger)

    3. Advanced Context Metrics Widget (Token Velocity & Time-to-Full)

    Motivation:
    While the existing Context Percentage widgets are great, we can provide even more proactive context management by calculating token velocity. This helps users understand how quickly they are consuming the context window and predict when it will be full, allowing them to /compact before hitting the limit unexpectedly. This was a core feature of my TS implementation (contextCollector.ts).

    Implementation Idea:
    This requires parsing the transcript_path JSONL file, similar to how ccstatusline already calculates token counts. The key is to find the first and last entries with usage data to calculate the rate.

    • Token Velocity (tokens/minute):
      tokenDiff = lastEntry.totalTokens - firstEntry.totalTokens
      timeDiffMinutes = (lastEntry.timestamp - firstEntry.timestamp) / 60000
      velocity = tokenDiff / timeDiffMinutes
    • Estimated Time-to-Full (minutes):
      timeToFull = (contextWindowSize - currentTokens) / velocity

    My documentation for this feature (CONTEXT_FEATURES.md) provides more detail. This could be a new widget or an enhancement to the existing context widgets.

    Display Example:

    • ⛁ 125.4k/200k (62%) ↑453/min ~2h15m
      (Current/Total (Percent) | Velocity | Est. Time-to-Full)

    4. Anthropic API Status Widget

    Motivation:
    Occasionally, unexpected behavior or slowdowns can be caused by issues with the Anthropic API itself. This widget would periodically check https://status.anthropic.com/api/v2/status.json and display a simple status indicator.

    Implementation Idea:
    My Bash implementation (.claude/lib/renderers/anthropic_status_renderer.sh) did this with a 5-minute cache to avoid spamming the API. A TypeScript implementation could use a simple fetch call with similar caching logic.

    Display Example:

    • Operational: 🌐 Anthropic: ✅
    • Minor Issue: 🌐 Anthropic: ⚠️
    • Major Outage: 🌐 Anthropic: ❌

    Summary

    Integrating these widgets would make ccstatusline an even more indispensable tool by providing a complete, at-a-glance dashboard of Claude Code's real-time operational state.

    I believe these features align perfectly with the project's goal of providing a highly customizable and informative status line. I'm happy to provide code snippets or more details from my original implementation if it would be helpful.

    Thanks again for creating such an excellent utility

  2. coygeek commented on Aug 27, 2025

    @coygeek
    Author

    Title: Feature Request: Add Advanced Cost and Usage Analysis Widgets (Inspired by ccusage)

    Body:

    Hi @sirmalloc,

    First and foremost, thank you for creating ccstatusline! The TUI for configuration is brilliant, the Powerline support is beautiful, and the entire widget system is incredibly well-designed. It's an amazing tool.

    Before I found your project, I was working on my own statusline solution and also using the excellent ryoppippi/ccusage tool for deep analysis of my Claude Code usage. After comparing the projects, I realized that ccstatusline could become the ultimate real-time dashboard by incorporating some of the advanced data analysis capabilities found in ccusage.

    Currently, ccstatusline does a fantastic job of rendering the real-time data provided by Claude Code's statusline hook for the current session. The following proposals aim to expand its scope by adding widgets that perform deeper, historical analysis on the fly, much like ccusage does.

    Here are a few feature ideas, framed as new widgets:


    1. Daily Aggregate Cost Widget

    Motivation:
    The current SessionCost widget is great for the active conversation, but it doesn't provide the wider context of total daily spending. ccusage's daily report is one of its most valuable features. A widget that shows the running total for the entire day would help users manage their usage much more effectively without having to run a separate command.

    Implementation Idea:
    This would require the widget to do more than just parse the incoming JSON. On each update, it would need to:

    1. Identify the current date from the timestamp.
    2. Use a glob pattern (like ~/.config/claude/projects/**/*.jsonl) to find all of today's transcript files.
    3. Quickly parse these files to sum up the costUSD or calculate it from tokens, similar to how ccusage's loadDailyUsageData function works.
    4. Display both the current session cost and the running daily total.

    Display Example:
    💰 $0.23 session / $1.23 today

    2. Enhanced Session Block Widget

    Motivation:
    Your Block Timer widget is a great start. ccusage takes this concept further in its blocks --live command by treating the 5-hour window as a core billing unit, showing not just time but also cost, burn rate, and projections. This transforms the widget from a simple timer into a powerful forecasting tool.

    Implementation Idea:
    This widget would need to:

    1. Identify the current 5-hour block based on transcript timestamps, just as ccusage's _session-blocks.ts does.
    2. Calculate the cost accumulated within the current block.
    3. Calculate a cost burn rate (e.g., $/hr) based on recent activity.
    4. (Optional) Project the total cost for the block if the current burn rate continues.

    Display Example:
    📦 $0.45 block (2h 45m left) 🔥 $0.12/hr

    3. Configurable Cost Source Display

    Motivation:
    A brilliant debugging and trust-building feature in ccusage is its --cost-source option. Sometimes Claude Code's reported cost.total_cost_usd can differ slightly from a manual calculation based on token counts. This widget option would allow users to see both, or choose which one to trust.

    Implementation Idea:
    This would likely be a configuration option for the existing SessionCost widget.

    1. When set to both, the widget would take the cost.total_cost_usd from the input JSON.
    2. It would also calculate the cost itself by parsing the current transcript's tokens, just as ccusage does.
    3. It would then display both values for comparison.

    Display Example:
    💰 ($0.25 cc / $0.23 ccusage)

    4. Visual Burn Rate Indicator

    Motivation:
    A small but highly effective UI enhancement from ccusage is the --visual-burn-rate option. It provides an immediate, color-coded, at-a-glance indicator of token consumption speed, which is often easier to parse than a raw number.

    Implementation Idea:
    This would be a configuration option for the "Enhanced Session Block Widget" proposed above.

    1. Define thresholds for "Normal", "Moderate", and "High" burn rates (e.g., based on tokens/minute).
    2. Display a corresponding colored emoji or text next to the burn rate value. ccusage uses 🟢 for Normal, ⚠️ for Moderate, and 🚨 for High.

    Display Example:
    🔥 $0.12/hr 🟢 (Normal)


    Summary

    By adding these data-rich, analytical widgets, ccstatusline would evolve from a top-tier status line renderer into a comprehensive, real-time analysis dashboard inside the terminal. It would give users nearly all the benefits of running ccusage commands, but updated live with every interaction.

    I believe these features would be a huge value-add and would be happy to provide more context or snippets from my own explorations if it helps.

    Thanks again for the fantastic project

  3. sirmalloc commented on Aug 27, 2025

    @sirmalloc
    Owner

    Thanks for these suggestions. I'll just quick-hit some followup questions if you don't mind for each message numbered 1.x and 2.x for the items in the first and second messages respectively:

    1.1 - Can you point me to your implementation of the hook? I would need to get user consent when adding the widget to an existing install or consent when installing for the first time if any widgets require hooks, but this is doable with proper UX around user consent.

    1.2 - I can't find docs indicating that subagent_type is included in the statusline JSON. Maybe it's not documented, but I've checked the JSON Input Structure section of https://docs.anthropic.com/en/docs/claude-code/statusline and don't see it. What happens with parallel subagents running simultaneously?

    1.3 & 1.4 - Should be easy enough

    2.1 - Should be doable. I'm already parsing non-transcript specific jsonl files for the block timer widget to mimic how ccusage does so.

    2.2 - Also doable, I would just need price retrieval and caching

    2.3 - Are you referring to a toggle on the Session Cost widget that would switch between the statusline cost.total_cost_usd and one calculated off the session transcript? Should be fine, again, need price retrieval and caching mechanism in place first.

    2.4 - Are these configurable or static thresholds?

  4. self-assigned this
    on Aug 27, 2025
  5. coygeek commented on Aug 28, 2025

    @coygeek
    Author

    Regarding 1.1:


    Thanks for the quick reply, @sirmalloc!

    Absolutely. Here is the implementation for the hook from my 2025-08-09-statusline project that tracks the active tool.

    The core of the implementation is a simple Bash script, .claude/hooks/activity_hook.sh, that writes the current tool's state to a temporary JSON file. The statusline then reads this file to get real-time information.

    Here is the full code for the hook script:

    #!/bin/bash
    # Simple, file-based activity hook. No daemon communication.
    
    set -euo pipefail
    
    # Read JSON input from stdin
    input=$(cat)
    
    # Extract session and event info
    SESSION_ID=$(echo "$input" | jq -r '.session_id // "default"')
    HOOK_EVENT=$(echo "$input" | jq -r '.hook_event_name // empty')
    
    # Define the state file path
    STATE_FILE="/tmp/claude_tool_state_${SESSION_ID}.json"
    
    # Ensure the directory exists
    mkdir -p "$(dirname "$STATE_FILE")"
    
    case "$HOOK_EVENT" in
        "PreToolUse")
            TOOL_NAME=$(echo "$input" | jq -r '.tool_name // empty')
            if [ -n "$TOOL_NAME" ]; then
                # Write the current tool state as a simple JSON object
                jq -n \
                  --arg tool_name "$TOOL_NAME" \
                  --arg status "RUNNING" \
                  --arg start_time "$(date +%s)" \
                  '{tool_name: $tool_name, status: $status, start_time: $start_time}' > "$STATE_FILE"
            fi
            ;;
    
        "PostToolUse")
            # On completion, we can clear the state file
            rm -f "$STATE_FILE" 2>/dev/null || true
            ;;
    
        "Stop"|"SessionStop"|"SubagentStop")
            # Clear the state file on session/agent stop
            rm -f "$STATE_FILE" 2>/dev/null || true
            ;;
    esac
    
    # Always exit successfully
    exit 0

    How It Works

    1. PreToolUse: When Claude is about to use a tool, this hook fires. The script captures the tool_name and the current timestamp and writes a JSON object to a session-specific file (e.g., /tmp/claude_tool_state_abc123.json) with a status of RUNNING.
    2. PostToolUse / Stop: When the tool finishes or the session ends, these hooks fire and simply delete the state file.
    3. Statusline Integration: The statusline script then just has to read this temporary file. If the file exists, it knows a tool is running and can display its name and calculate the duration. If the file doesn't exist, it knows no tool is active.

    Configuration in .claude/settings.json

    This hook would be registered in the user's .claude/settings.json like this, targeting all tools with a * matcher:

    {
      "hooks": {
        "PreToolUse": [
          {
            "matcher": "*",
            "hooks": [
              {
                "type": "command",
                "command": "/path/to/project/.claude/hooks/activity_hook.sh"
              }
            ]
          }
        ],
        "PostToolUse": [
          {
            "matcher": "*",
            "hooks": [
              {
                "type": "command",
                "command": "/path/to/project/.claude/hooks/activity_hook.sh"
              }
            ]
          }
        ]
      }
    }

    Let me know if you have any other questions.

  6. coygeek commented on Aug 28, 2025

    @coygeek
    Author

    Regarding 1.2:


    You are right to point out that subagent_type is not in the official statusline documentation. My apologies for the confusion—I made an incorrect assumption by conflating my project's implementation with the standard payload provided by Claude Code. After reviewing the official docs you linked and my own project files, I can confirm the field is not directly available via the statusline's stdin JSON.

    My implementation gets this information through a workaround using Claude Code Hooks. This makes it more of a "power-user" feature, but I still think it's a valuable pattern. Here’s how it works:

    Implementation via Hooks

    The basic idea is to use hooks to write the current sub-agent's state to a temporary file, which the statusline script then reads on each update.

    1. Use SubagentStart and SubagentStop Hooks:
      The official documentation for hooks confirms the existence of SubagentStart and SubagentStop events. We can register a simple script to run on these events.

      (Example .claude/config/hooks.json)

      {
        "hooks": {
          "SubagentStart": [{
            "name": "subagent_tracker",
            "script": ".claude/hooks/activity_hook.sh"
          }],
          "SubagentStop": [{
            "name": "subagent_tracker",
            "script": ".claude/hooks/activity_hook.sh"
          }]
        }
      }
    2. The Hook Script (activity_hook.sh):
      This script reads the hook's JSON input and writes the active sub-agent's name to a state file. When the sub-agent stops, it clears the file.

      #!/bin/bash
      set -euo pipefail
      
      input=$(cat)
      SESSION_ID=$(echo "$input" | jq -r '.session_id // "default"')
      HOOK_EVENT=$(echo "$input" | jq -r '.hook_event_name // ""')
      STATE_FILE="/tmp/claude_agent_state_${SESSION_ID}.json"
      
      if [[ "$HOOK_EVENT" == "SubagentStart" ]]; then
          # The tool_name for a subagent task is the agent's name
          AGENT_NAME=$(echo "$input" | jq -r '.tool_name // ""')
          jq -n --arg name "$AGENT_NAME" '{"active_agent": $name}' > "$STATE_FILE"
      elif [[ "$HOOK_EVENT" == "SubagentStop" ]]; then
          # Clear the state file when the subagent is done
          rm -f "$STATE_FILE"
      fi
    3. The Statusline Script:
      Your statusline script (like ccstatusline) can then read this state file on each render.

      SESSION_ID=$(echo "$STATUSLINE_JSON_INPUT" | jq -r '.session_id')
      STATE_FILE="/tmp/claude_agent_state_${SESSION_ID}.json"
      
      ACTIVE_AGENT=""
      if [[ -f "$STATE_FILE" ]]; then
          ACTIVE_AGENT=$(jq -r '.active_agent // ""' "$STATE_FILE")
      fi
      
      if [[ -n "$ACTIVE_AGENT" ]]; then
          # Render the agent widget, e.g., "🤖 (Reviewer)"
      fi

    Regarding Parallel Sub-Agents

    That's an excellent question. Based on the documentation (en/docs/claude-code/sub-agents), sub-agents are invoked via the Task tool. The main agent delegates a task and waits for the result. While I haven't seen explicit confirmation of parallel execution, this model suggests they are likely invoked serially.

    The file-based state tracking I described would naturally only show the most recently started sub-agent, which works perfectly for a serial workflow. If true parallelism is possible, the hook system might need a more sophisticated state management approach (like appending to a JSON array of active agents), but for the common case, this seems to be a solid starting point.

    Thanks again for your engagement on this. Let me know if this clarifies my thinking. I believe adding this as an optional, advanced widget could be a great way to surface this deeper contextual information for users who are willing to set up the necessary hooks.

  7. coygeek commented on Aug 28, 2025

    @coygeek
    Author

    Regarding 2.3:


    Yes, that's exactly what I had in mind. A toggle on the SessionCost widget would be perfect. It would be great if it could switch between showing the reported cost.total_cost_usd from the hook and a cost calculated on-the-fly from the session transcript. A side-by-side comparison of both would be a fantastic bonus for debugging.

    I understand this depends on the price retrieval and caching mechanism you mentioned, which makes total sense as a prerequisite.

  8. coygeek commented on Aug 28, 2025

    @coygeek
    Author

    Regarding 2.4:


    I believe making the thresholds configurable would be the ideal approach, as it fits perfectly with the excellent TUI-based configuration philosophy you've already established in ccstatusline.

    Rationale for Configurability

    1. Varying Cost Sensitivities: An individual developer might have different cost thresholds compared to a developer on an enterprise team with a larger budget.
    2. Model-Specific Costs: As users switch between models like Haiku, Sonnet, and Opus, their cost-per-hour will change dramatically. Configurable thresholds would allow users to set appropriate levels for their primary model.
    3. Task-Specific Usage: A developer primarily using Claude Code for codebase Q&A will have a much lower burn rate than someone using it for large-scale code generation or refactoring.

    Proposed Defaults (Data-Driven)

    With that said, providing sensible defaults is key for a great out-of-the-box experience. I looked through the official Anthropic documentation to find a basis for these defaults.

    The Claude Code costs documentation states:

    The average cost is $6 per developer per day, with daily costs remaining below $12 for 90% of users.

    Assuming a standard 8-hour workday, we can derive some data-driven hourly rates:

    • Average Rate: $6 / 8 hours = $0.75/hr
    • High-Usage Rate (90th percentile): $12 / 8 hours = $1.50/hr

    Based on this, I'd propose the following defaults:

    • Normal (🟢): < $0.75/hr (Below average usage)
    • Moderate (⚠️): $0.75/hr – $1.50/hr (Average to high-end usage)
    • High (🚨): > $1.50/hr (Exceeding the 90th percentile daily rate)

    These defaults are grounded in Anthropic's own usage metrics and would provide a very meaningful starting point for users.

    Implementation Idea

    Looking at the project's TUI structure in src/tui/components/, this could be implemented similarly to how widgets like CurrentWorkingDir or CustomCommand have their own editors for custom properties (like path segments or timeout values).

    A new editor screen could be added for the "Enhanced Session Block Widget" that allows the user to set the numeric dollar-per-hour thresholds for the "Moderate" and "High" levels.

    So, in summary: configurable thresholds with data-driven defaults.

    Thanks again for your engagement on this! Let me know if you have any more questions.

  9. coygeek commented on Sep 14, 2025

    @coygeek
    Author

    I added the Anthropic Status (from https://status.anthropic.com/) to my ccstatusline, since im not waiting for official support from the author. For anyone following this thread, you can use this to get this important feature working immediately in your own ccstatusline.


    Since the "Anthropic API Status" widget is not a built-in feature, you can create it yourself using the powerful Custom Command widget. This is the perfect way to extend ccstatusline with any information you want.

    Based on the code snippets, the Custom Command widget can run any shell command and display its output. We'll write a small shell script that fetches the status, formats it with the correct emoji, and implements caching, just like you described.

    Here is a step-by-step guide to get this working on your macOS setup.

    Step 1: Create the Status Check Script

    First, we need a script that performs the logic. This script will:

    1. Check for a cached status file.
    2. If the cache is old or doesn't exist, fetch the latest status from the Anthropic API.
    3. Parse the JSON to get the status indicator.
    4. Print the formatted output with the correct emoji.

    You will need jq, a lightweight command-line JSON processor. If you don't have it, you can install it easily with Homebrew:

    brew install jq

    Now, let's create the script. A good place to store custom scripts for ccstatusline is in its configuration directory.

    1. Create a directory for your scripts:

      mkdir -p ~/.config/ccstatusline/scripts
    2. Create the script file:

      touch ~/.config/ccstatusline/scripts/anthropic_status.sh
    3. Paste the following code into the script file (~/.config/ccstatusline/scripts/anthropic_status.sh):

    #!/bin/bash
    
    # --- Configuration ---
    CACHE_FILE="/tmp/anthropic_status.json"
    CACHE_DURATION_SECONDS=300 # 5 minutes
    
    # --- Logic ---
    # Function to fetch and update the cache
    fetch_status() {
      curl -s 'https://status.anthropic.com/api/v2/status.json' > "$CACHE_FILE"
    }
    
    # Check if cache exists and is recent
    if [ -f "$CACHE_FILE" ]; then
      # Get the file's modification time
      last_modified=$(stat -f "%m" "$CACHE_FILE")
      current_time=$(date +%s)
      age=$((current_time - last_modified))
    
      # If cache is older than our duration, fetch again
      if [ "$age" -gt "$CACHE_DURATION_SECONDS" ]; then
    	fetch_status
      fi
    else
      # If cache file doesn't exist, fetch it
      fetch_status
    fi
    
    # Read status from cache and format output
    if [ -f "$CACHE_FILE" ] && [ -s "$CACHE_FILE" ]; then
      indicator=$(jq -r '.status.indicator' "$CACHE_FILE")
    
      case "$indicator" in
    	"none")
    	  echo "🌐 Anthropic: ✅"
    	  ;;
    	"minor")
    	  echo "🌐 Anthropic: ⚠️"
    	  ;;
    	"major" | "critical")
    	  echo "🌐 Anthropic: ❌"
    	  ;;
    	*)
    	  echo "🌐 Anthropic: ❓"
    	  ;;
      esac
    else
      # Fallback if fetching or parsing fails
      echo "🌐 Anthropic: ❔"
    fi
    1. Make the script executable: This is a crucial step!
    chmod +x ~/.config/ccstatusline/scripts/anthropic_status.sh

    Step 2: Add the Custom Command Widget to ccstatusline

    Now that you have your script, you need to tell ccstatusline to run it.

    1. Open the ccstatusline configuration TUI:
      As shown in the snippets, you can run this command in your terminal:

      npx ccstatusline@latest
    2. In the TUI, navigate the menu:

      • Select "Add a new widget to the statusline".
      • Scroll down and select "Custom Command".
    3. Configure the widget:

      • Command: Enter the full, absolute path to the script you just created.
        /Users/your_username/.config/ccstatusline/scripts/anthropic_status.sh
        
        (Replace your_username with your actual macOS username. You can find it by running whoami in the terminal).
      • Timeout (ms): Set a reasonable timeout, like 5000 (5 seconds).
      • Keep ANSI colors: You can leave this as false.
      • Raw value mode: You can leave this as false.
    4. Save your configuration:

      • Select "Done".
      • Your new "Custom Command" widget will appear in the list. You can use the arrow keys to move it to your desired position.
      • Select "Save and Exit".

    That's it! The next time your status line refreshes, it will execute your script, and you will see the Anthropic API status appear. Thanks to the caching in the script, it will only hit the API once every 5 minutes, making it very efficient.

  10. maxiride commented on Aug 20, 2026

    @maxiride

    Just stumbled upon here, is the token burn projection being worked on? So to have an estimate if the user will consume all the 5h / 7d limits before the end of the window.

  11. eric-engberg commented on Oct 9, 2026

    @eric-engberg
    Contributor

    @maxiride the 5-hour projection is open here as #699: Session Forecast projects the window's usage at reset from the recent burn rate, and Session Limit Timer shows when you'd hit the limit at that pace.

    For the 7-day windows, eric-engberg#80 adds Weekly Limit Timer and Weekly Fable Limit Timer. They show when you'd hit the weekly limit at this week's average pace, counted from the window's own start, and only when that comes before the reset. I'll open it here after #699. Session Cost Rate (#671) is merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions