1
submitted 2 weeks ago by Banthex@feddit.org to c/linux@lemmy.world

Hello,

i am a new noob to hyprland and i used claude code to edit my dotfiles. For that i used ccusage.

Greetings!

top 2 comments
sorted by: hot top controversial new old
[-] Banthex@feddit.org 0 points 2 weeks ago

Waybar with Claude Code & Codex Usage Display

This guide shows how to configure Waybar (for Wayland/Hyprland) with live status displays for Claude Code and Codex. The modules show current usage and rate limits in real-time in the status bar.

๐Ÿ“ธ Example

Waybar displays two modules:

  • CC (Claude Code): Shows 5h-block status with progress bar
  • COD (Codex): Shows rate-limit status with progress bar

Example output:

CC ๐Ÿ•2h45m  67% โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–‘  โ”‚  COD ๐Ÿ•4h12m  23% โ–ˆโ–ˆโ–‘โ–‘โ–‘โ–‘โ–‘โ–‘

๐Ÿ”ง Prerequisites

System

  • Waybar (for Wayland/Hyprland)
  • Linux (Arch Linux, Ubuntu, etc.)
  • Bash Shell
  • jq (JSON Processor)

Node.js Tools

One of the following package managers:

  • npx (comes with Node.js)
  • bunx (Bun)
  • pnpm

Claude Code & Codex Tools

  • ccusage: npm install -g ccusage or via npx ccusage
  • @ccusage/codex: npm install -g @ccusage/codex or via npx @ccusage/codex

๐Ÿ“ File Structure

~/.config/waybar/
โ”œโ”€โ”€ config.jsonc              # Waybar main configuration
โ”œโ”€โ”€ style.css                 # Waybar styling
โ””โ”€โ”€ scripts/
    โ”œโ”€โ”€ ccusage-statusline.sh    # Claude Code status script
    โ”œโ”€โ”€ codex-statusline.sh      # Codex status script
    โ””โ”€โ”€ api-config.sh (optional) # API configuration

๐Ÿ“ Step 1: Waybar Configuration

Open ~/.config/waybar/config.jsonc and add the two modules:

1.1 Add modules to modules-center

{
  "modules-center": [
    // ... other modules ...
    "custom/ccusage",
    "custom/codex-usage",
    // ... other modules ...
  ],

  // ... rest of config ...

  "custom/ccusage": {
    "exec": "~/.config/waybar/scripts/ccusage-statusline.sh",
    "interval": 300,
    "format": "{}",
    "tooltip-format": "ccusage daily + monthly totals (Claude Code)\nClick to refresh",
    "on-click": "~/.config/waybar/scripts/ccusage-statusline.sh"
  },

  "custom/codex-usage": {
    "exec": "~/.config/waybar/scripts/codex-statusline.sh",
    "interval": 300,
    "format": "{}",
    "tooltip-format": "ccusage codex daily + monthly totals\nClick to refresh",
    "on-click": "~/.config/waybar/scripts/codex-statusline.sh"
  }
}

Explanation:

  • exec: Path to the script that provides the data
  • interval: Update interval in seconds (300s = 5min)
  • format: Display format (here directly the script output)
  • on-click: Clicking triggers a manual script update

๐Ÿ“ Step 2: Waybar Styling

Add the styling for the modules in ~/.config/waybar/style.css:

#custom-ccusage {
  background-color: rgba(40, 42, 54, 0.8);
  padding: 4px 10px;
  margin: 2px 4px;
  border-radius: 8px;
  font-family: 'JetBrainsMono Nerd Font Mono';
  font-size: 11px;
  color: #ff6ac1;  /* Pink for Claude Code */
}

#custom-codex-usage {
  background-color: rgba(40, 42, 54, 0.8);
  padding: 4px 10px;
  margin: 2px 4px;
  border-radius: 8px;
  font-family: 'JetBrainsMono Nerd Font Mono';
  font-size: 11px;
  color: #6ef2d0;  /* Turquoise for Codex */
}

Customizations:

  • color: Text color (can be changed as desired)
  • font-family: Nerd Font for icons (install JetBrainsMono Nerd Font)
  • font-size: Adjust font size

๐Ÿ“ Step 3: Create Scripts

3.1 Create script directory

mkdir -p ~/.config/waybar/scripts
chmod +x ~/.config/waybar/scripts/*.sh

3.2 Claude Code Script

Create ~/.config/waybar/scripts/ccusage-statusline.sh:

#!/bin/bash

# Compact ccusage summary for Waybar (daily totals).

CONFIG_FILE="$HOME/.config/waybar/scripts/api-config.sh"
[ -f "$CONFIG_FILE" ] && source "$CONFIG_FILE"

# Prefer explicitly set binary, then cached npx installs, then package runners.
choose_runner() {
  if [ -n "$CCUSAGE_BIN" ] && command -v "$CCUSAGE_BIN" >/dev/null 2>&1; then
    echo "$CCUSAGE_BIN"
    return
  fi

  # Reuse first cached npx install if present to avoid network lookups.
  CACHE_BIN=$(find "$HOME/.npm/_npx" -path '*/node_modules/.bin/ccusage' -maxdepth 5 -print -quit 2>/dev/null)
  if [ -n "$CACHE_BIN" ]; then
    echo "$CACHE_BIN"
    return
  fi

  if command -v ccusage >/dev/null 2>&1; then
    echo "ccusage"
    return
  fi
  if command -v bunx >/dev/null 2>&1; then
    echo "bunx ccusage@latest"
    return
  fi
  if command -v pnpm >/dev/null 2>&1; then
    echo "pnpm dlx ccusage"
    return
  fi
  if command -v npx >/dev/null 2>&1; then
    echo "npx --yes ccusage@latest"
    return
  fi
}

RUNNER=$(choose_runner)
[ -z "$RUNNER" ] && { echo "CC ?"; exit 0; }

# Run command with a timeout to avoid hanging on network fetches.
run_cmd() {
  local cmd=$1
  if command -v timeout >/dev/null 2>&1; then
    timeout 20s bash -lc "$cmd"
  else
    bash -lc "$cmd"
  fi
}

# Helper: call ccusage command and emit cost/tokens TSV.
get_totals() {
  local cmd=$1
  local json
  json=$(NO_COLOR=1 run_cmd "$RUNNER $cmd --json --offline" 2>/dev/null)
  if [ -z "$json" ]; then
    return 1
  fi
  printf '%s' "$json" | jq -r '(.totals.totalCost // .totals.costUSD // 0) as $c | (.totals.totalTokens // 0) as $t | [$c, $t] | @tsv' 2>/dev/null
}

format_tokens_short() {
  local tokens=$1
  if awk -v t="$tokens" 'BEGIN { exit (t >= 1000000000) ? 0 : 1 }'; then
    awk -v t="$tokens" 'BEGIN { printf("%.1fB", t/1000000000) }'
  elif awk -v t="$tokens" 'BEGIN { exit (t >= 1000000) ? 0 : 1 }'; then
    awk -v t="$tokens" 'BEGIN { printf("%.1fM", t/1000000) }'
  elif awk -v t="$tokens" 'BEGIN { exit (t >= 1000) ? 0 : 1 }'; then
    awk -v t="$tokens" 'BEGIN { printf("%.0fk", t/1000) }'
  else
    printf "%s" "$tokens"
  fi
}

build_progress_bar() {
  local percent=$1
  local segments=8
  local filled=$((percent * segments / 100))
  local empty=$((segments - filled))
  [ $filled -gt $segments ] && filled=$segments
  [ $empty -lt 0 ] && empty=0

  local bar=""
  for ((i = 0; i < filled; i++)); do bar+="โ–ˆ"; done
  for ((i = 0; i < empty; i++)); do bar+="โ–‘"; done
  printf "%s" "$bar"
}

block_progress() {
  # Show current active 5h billing block status
  local json
  json=$(NO_COLOR=1 run_cmd "$RUNNER blocks --json --offline" 2>/dev/null)
  if [ -z "$json" ]; then
    return 1
  fi

  # Extract active block info: cost, end time
  local block_info
  block_info=$(printf '%s' "$json" | jq -r '
    .blocks[]
    | select(.isActive == true and .isGap == false)
    | [.costUSD, .endTime, .tokenCounts.inputTokens + .tokenCounts.outputTokens] | @tsv
  ' 2>/dev/null) || return 1

  if [ -z "$block_info" ]; then
    # No active block, show "idle"
    printf "โธ idle"
    return 0
  fi

  local cost end_time tokens
  read -r cost end_time tokens <<<"$block_info"

  # Estimate block limit: Claude Code typically allows ~$15-20 per 5h block
  # We'll use $15 as baseline (adjustable via CLAUDE_BLOCK_LIMIT_USD)
  local block_limit="${CLAUDE_BLOCK_LIMIT_USD:-15}"

  local percent
  percent=$(awk -v c="$cost" -v l="$block_limit" 'BEGIN { if (l <= 0) { print 0 } else { printf("%.0f", (c / l) * 100) } }') || percent=0
  [ -z "$percent" ] && percent=0
  [ "$percent" -gt 100 ] && percent=100
  [ "$percent" -lt 0 ] && percent=0

  # Calculate time remaining until block ends
  local now_epoch end_epoch time_remaining
  now_epoch=$(date +%s)
  end_epoch=$(date -d "$end_time" +%s 2>/dev/null)
  if [ -n "$end_epoch" ] && [ "$end_epoch" -gt "$now_epoch" ]; then
    time_remaining=$((end_epoch - now_epoch))
    local hours=$((time_remaining / 3600))
    local mins=$(( (time_remaining % 3600) / 60 ))
    local time_str="${hours}h${mins}m"
  else
    local time_str="ending"
  fi

  local bar
  bar=$(build_progress_bar "$percent")
  printf "๐Ÿ•%s %3d%% %s" "$time_str" "$percent" "$bar"
}

format_line() {
  local label=$1
  local cost=$2
  printf "%s $%.2f" "$label" "$cost"
}

BLOCK_STATUS=$(block_progress)

if [ -z "$BLOCK_STATUS" ]; then
  echo "CC โ€ฆ"
  exit 0
fi

echo "CC $BLOCK_STATUS"

3.3 Codex Script

Create ~/.config/waybar/scripts/codex-statusline.sh:

#!/bin/bash

# Compact @ccusage/codex summary for Waybar (daily + monthly).

CONFIG_FILE="$HOME/.config/waybar/scripts/api-config.sh"
[ -f "$CONFIG_FILE" ] && source "$CONFIG_FILE"

choose_runner() {
  # Explicit override.
  if [ -n "$CCUSAGE_CODEX_BIN" ] && command -v "$CCUSAGE_CODEX_BIN" >/dev/null 2>&1; then
    echo "$CCUSAGE_CODEX_BIN"
    return
  fi

  # Local install via npm prefix.
  LOCAL_BIN="$HOME/.local/share/ccusage-codex/node_modules/.bin/ccusage-codex"
  if [ -x "$LOCAL_BIN" ]; then
    echo "$LOCAL_BIN"
    return
  fi

  # Cached npx install.
  CACHE_BIN=$(find "$HOME/.npm/_npx" -path '*@ccusage/codex*/node_modules/.bin/codex' -maxdepth 5 -print -quit 2>/dev/null)
  [ -z "$CACHE_BIN" ] && CACHE_BIN=$(find "$HOME/.npm/_npx" -path '*@ccusage/codex*/node_modules/.bin/ccusage-codex' -maxdepth 5 -print -quit 2>/dev/null)
  if [ -n "$CACHE_BIN" ]; then
    echo "$CACHE_BIN"
    return
  fi

  if command -v bunx >/dev/null 2>&1; then
    echo "bunx @ccusage/codex@latest"
    return
  fi
  if command -v pnpm >/dev/null 2>&1; then
    echo "pnpm dlx @ccusage/codex"
    return
  fi
  if command -v npx >/dev/null 2>&1; then
    echo "npm_config_offline=true npx --yes @ccusage/codex@latest"
    return
  fi

  # Last resort: plain codex in PATH (may collide with other tools).
  if command -v codex >/dev/null 2>&1; then
    echo "codex"
    return
  fi
}

RUNNER=$(choose_runner)
[ -z "$RUNNER" ] && { echo "codex ?"; exit 0; }

run_cmd() {
  local cmd=$1
  if command -v timeout >/dev/null 2>&1; then
    timeout 20s bash -lc "$cmd"
  else
    bash -lc "$cmd"
  fi
}

get_totals() {
  local cmd=$1
  local json
  json=$(NO_COLOR=1 run_cmd "$RUNNER $cmd --json --offline" 2>/dev/null)
  if [ -z "$json" ]; then
    return 1
  fi
  printf '%s' "$json" | jq -r '(.totals.totalCost // .totals.costUSD // 0) as $c | (.totals.totalTokens // 0) as $t | [$c, $t] | @tsv' 2>/dev/null
}

format_tokens_short() {
  local tokens=$1
  if awk -v t="$tokens" 'BEGIN { exit (t >= 1000000000) ? 0 : 1 }'; then
    awk -v t="$tokens" 'BEGIN { printf("%.1fB", t/1000000000) }'
  elif awk -v t="$tokens" 'BEGIN { exit (t >= 1
[-] HappyFrog@lemmy.blahaj.zone 1 points 2 weeks ago

Did you write this post with AI too? What's with the emojis?

this post was submitted on 28 Nov 2025
1 points (66.7% liked)

Linux

14363 readers
7 users here now

Welcome to c/linux!

Welcome to our thriving Linux community! Whether you're a seasoned Linux enthusiast or just starting your journey, we're excited to have you here. Explore, learn, and collaborate with like-minded individuals who share a passion for open-source software and the endless possibilities it offers. Together, let's dive into the world of Linux and embrace the power of freedom, customization, and innovation. Enjoy your stay and feel free to join the vibrant discussions that await you!

Rules:

  1. Stay on topic: Posts and discussions should be related to Linux, open source software, and related technologies.

  2. Be respectful: Treat fellow community members with respect and courtesy.

  3. Quality over quantity: Share informative and thought-provoking content.

  4. No spam or self-promotion: Avoid excessive self-promotion or spamming.

  5. No NSFW adult content

  6. Follow general lemmy guidelines.

founded 2 years ago
MODERATORS