Skip to content

Instantly share code, notes, and snippets.

@agrublev
Created September 3, 2026 13:25
Show Gist options
  • Select an option

  • Save agrublev/282d6054044953ddcac1c9f09dec9997 to your computer and use it in GitHub Desktop.

Select an option

Save agrublev/282d6054044953ddcac1c9f09dec9997 to your computer and use it in GitHub Desktop.
STATUSLINE!
#!/bin/bash
# Installs the Claude Code statusline script and wires it up in ~/.claude/settings.json.
# Run this on the target (server) machine: bash install-statusline.sh
set -euo pipefail
CLAUDE_DIR="$HOME/.claude"
STATUSLINE_PATH="$CLAUDE_DIR/statusline-command.sh"
SETTINGS_PATH="$CLAUDE_DIR/settings.json"
mkdir -p "$CLAUDE_DIR"
cat > "$STATUSLINE_PATH" << 'STATUSLINE_EOF'
#!/bin/bash
# Claude Code status line.
# Layout: context | cost | model | effort | cwd | repo | branch
# Repo and branch are omitted entirely outside a git repository.
# jq emits numbers with a dot; this shell runs under a comma-decimal locale,
# where printf %f then rejects "8.4" and silently yields 0. Force C numerics
# for the conversions below. Not LC_ALL, which would also affect path text.
export LC_NUMERIC=C
input=$(cat)
# One jq call, one field per line. Newline-delimited (not @tsv) on purpose:
# with IFS=$'\t', bash `read` collapses runs of tab because tab is IFS
# whitespace, so a single empty field silently shifts every later field left.
fields=()
while IFS= read -r line; do fields+=("$line"); done < <(
printf '%s' "$input" | jq -r '
[
(.context_window.used_percentage // "" | tostring),
(.cost.total_cost_usd // "" | tostring),
(.model.display_name // ""),
(if .effort.level then .effort.level
elif .thinking.enabled == true then "on"
elif .thinking.enabled == false then "off"
else "" end),
(.workspace.current_dir // .cwd // ""),
(.workspace.repo | if . then ((.owner // "") + "/" + (.name // "")) else "" end)
] | .[]
' 2>/dev/null
)
used_pct="${fields[0]}"
cost="${fields[1]}"
model="${fields[2]:-Claude}"
effort="${fields[3]}"
raw_cwd="${fields[4]}"
repo="${fields[5]}"
# Abbreviate home for display.
disp_cwd="$raw_cwd"
case "$disp_cwd" in
"$HOME") disp_cwd="~" ;;
"$HOME"/*) disp_cwd="~${disp_cwd#"$HOME"}" ;;
esac
# Single lock-free git call, guarded on the directory still existing.
# Silent outside a repo, on detached HEAD, or if cwd was deleted.
branch=""
if [ -n "$raw_cwd" ] && [ -d "$raw_cwd" ]; then
branch=$(git -C "$raw_cwd" --no-optional-locks symbolic-ref --short -q HEAD 2>/dev/null)
fi
C_CTX=$'\033[2;32m'
C_COST=$'\033[2;31m'
C_MODEL=$'\033[2;36m'
C_EFFORT=$'\033[2;35m'
C_DIR=$'\033[2;34m'
C_REPO=$'\033[2;90m'
C_BRANCH=$'\033[2;33m'
RESET=$'\033[0m'
SEP=" "
# Collect only non-empty segments, so an absent field leaves no separator
# or placeholder behind.
parts=()
case "$used_pct" in
''|*[!0-9.]*) ;;
*) parts+=("${C_CTX}Ctx $(printf '%.0f' "$used_pct" 2>/dev/null)%${RESET}") ;;
esac
case "$cost" in
''|*[!0-9.]*) ;;
*) parts+=("${C_COST}\$$(printf '%.2f' "$cost" 2>/dev/null)${RESET}") ;;
esac
parts+=("${C_MODEL}${model}${RESET}")
[ -n "$effort" ] && parts+=("${C_EFFORT}Effort: ${effort}${RESET}")
[ -n "$disp_cwd" ] && parts+=("${C_DIR}${disp_cwd}${RESET}")
[ -n "$repo" ] && parts+=("${C_REPO}${repo}${RESET}")
[ -n "$branch" ] && parts+=("${C_BRANCH}${branch}${RESET}")
line=""
for p in "${parts[@]}"; do
if [ -z "$line" ]; then line="$p"; else line="${line}${SEP}${p}"; fi
done
# %s not %b: the colour vars hold literal ESC bytes already, and %b would
# expand backslash sequences inside a path or branch name.
printf '%s' "$line"
STATUSLINE_EOF
chmod +x "$STATUSLINE_PATH"
echo "Wrote $STATUSLINE_PATH"
if ! command -v jq >/dev/null 2>&1; then
echo "Warning: 'jq' is not installed on this machine — the statusline script requires it." >&2
fi
STATUSLINE_CMD="bash $STATUSLINE_PATH"
if [ -f "$SETTINGS_PATH" ]; then
if ! command -v jq >/dev/null 2>&1; then
echo "Error: jq is required to safely update $SETTINGS_PATH. Install jq and re-run." >&2
exit 1
fi
tmp=$(mktemp)
jq --arg cmd "$STATUSLINE_CMD" '.statusLine = {"type": "command", "command": $cmd}' "$SETTINGS_PATH" > "$tmp"
mv "$tmp" "$SETTINGS_PATH"
echo "Updated statusLine in $SETTINGS_PATH"
else
cat > "$SETTINGS_PATH" << SETTINGS_EOF
{
"statusLine": {
"type": "command",
"command": "$STATUSLINE_CMD"
}
}
SETTINGS_EOF
echo "Created $SETTINGS_PATH with statusLine config"
fi
echo "Done. Restart Claude Code (or start a new session) to see the statusline."
@agrublev

agrublev commented Sep 3, 2026

Copy link
Copy Markdown
Author

curl -fsSL https://gist.githubusercontent.com/agrublev/282d6054044953ddcac1c9f09dec9997/raw/71c6419ef78eda77c284f01f556e542e2f7e8714/statusline.sh | bash

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