lirantal/statusline-creator-skill/statusline-creator

Trust tier 3
  • community
Source check pending

Checking that the SKILL.md file is still in the repository.

Builds a Claude Code statusline from scratch or extends an existing one. A statusline is a live status bar that runs a shell script after every Claude response and displays data — security scans, git status, API quotas, build state — directly in the session. Use this skill when the user says "create a statusline", "make a statusline for X", "add X to my statusline", "show Y in the status bar", "build a statusline plugin", or "I want live data in my Claude session". Trigger even if the user just describes wanting live feedback during a Claude session without naming "statusline" explicitly. The skill drives from idea to a working, installed, tested statusline without requiring the user to direct every step.

Install

npx vskill@latest install lirantal/statusline-creator-skill/statusline-creator

SKILL.md

Statusline Creator

Instructions

A Claude Code statusline is a bash script that Claude runs after every response. It reads session metadata on stdin and prints a colored line to stdout — giving you live, contextual data without leaving the session.

The key design challenge: the statusline must render instantly, every time. There are two valid execution models — choose based on measured speed:

  • Inline execution: run the command directly in the script. Only viable if the

operation reliably completes in under ~300ms (fast HTTP endpoints, local file reads, cheap shell commands). Must be benchmarked first — never assume an operation is fast.

  • Background + cache: the script always renders from cache; a background process

refreshes it on a TTL. Required for any operation that is slow, variable, or potentially blocking (CLI scanners, external APIs, network calls to remote services).

Before choosing a model, benchmark the operation — see Step 1.

Read references/protocol.md at the start of every session — it covers the stdin JSON schema, the settings.json format, and ANSI output rules. The authoritative reference for the protocol is the official Claude Code statusline documentation at https://code.claude.com/docs/en/statusline.md — check it for new fields or behaviors not yet reflected in the reference files. Read references/implementation-patterns.md when writing or debugging the script — it covers the caching pattern, exit code handling, state machine, and jq recipes.


Step 1: Understand what the user wants to show

Ask the user what data source they want in their statusline. Common categories:

  • Security tools — snyk test, trivy, semgrep, SAST/SCA/IaC scanners
  • Git/project state — branch, dirty files, CI status, PR state
  • Resource usage — API quotas, context window, cost, rate limits
  • Build/test state — last test run result, coverage, lint status
  • Cloud/infra — Kubernetes pod state, deploy status, environment

For each data source, establish:

  1. What CLI command or HTTP request produces the data?
  2. Benchmark its actual runtime — run it 3 times and record the wall-clock time:

``bash time <command> # run 3× and note the range ``

  • Under ~300ms consistently → inline execution is viable
  • Over ~300ms, variable, or potentially blocking → use background + cache
  1. What output format does it produce? (JSON, plain text, exit code only?)
  2. What states should the statusline show? (clean, issues found, scanning, unavailable, auth error)

Done when: You have a concrete data source, its command, its output format, and a list of states.


Step 2: Design the output line

Plan the display format before writing any code. A good statusline line has:

  • A label identifying the tool (e.g. 🔒 snyk, 🌿 git, ☁ k8s)
  • Segments separated by │ — one per logical data group
  • Color-coded counts or status — use severity/urgency to drive color choice
  • A scan age indicator when results come from a cache (· 5m ago)
  • A spinner ⟳ when a background refresh is running

Design the full set of states the script will display:

label │ <primary result> │ <secondary result> │ <project> · <age> ⟳
label │ ✔ clean │ project · 2m ago
label │ scanning...
label │ no supported files
label │ ⚠ auth required run: <cmd>

Use ANSI RGB colors. Standard palette for security tools (see references/implementation-patterns.md):

  • Critical → Red \033[38;2;255;85;85m
  • High → Orange \033[38;2;255;165;0m
  • Medium → Yellow \033[38;2;255;215;0m
  • Clean/OK → Green \033[38;2;80;250;123m
  • Label/dim → \033[38;2;100;170;255m / \033[38;2;128;128;128m

Done when: Every state the script can be in has a corresponding output line designed.


Step 3: Implement the script

Create statusline.sh in the project root. The structure depends on the execution model chosen in Step 1 (based on the benchmark results).

If using inline execution (operation benchmarked at <300ms):

  1. Configuration block — env vars with defaults (TOOL_BIN, display toggles)
  2. Color constants — define all ANSI codes as variables; never inline raw escapes
  3. Read stdin — SESSION=$(cat) — captures Claude's JSON; parse fields as needed
  4. Run the operation directly — execute the command and capture its output/exit code
  5. Build segment functions — one per data source; handle unavailable/auth error states
  6. Compose final output — printf the assembled line with separators

If using background + cache (operation benchmarked at >300ms or variable):

  1. Configuration block — env vars with defaults (TOOL_BIN, CACHE_TTL, display toggles)
  2. Color constants — define all ANSI codes as variables; never inline raw escapes
  3. Read stdin — SESSION=$(cat) — captures Claude's JSON; parse fields as needed
  4. Determine project root — git rev-parse --show-toplevel 2>/dev/null || pwd
  5. Cache paths — hash the project path with cksum for stable, per-project cache keys
  6. `file_age()` helper — returns age in seconds of any file; 999999 if missing
  7. `trigger_scan_bg()` function — atomic mkdir-based lock, runs scan in subshell, captures exit code explicitly, writes noscan sentinel on exit 3
  8. Trigger stale scans — compare age to TTL; call trigger functions
  9. Build segment functions — one per data source; check cache/noscan/lock states and return the formatted string for that segment
  10. Compose final output — printf the assembled line with separators

See references/implementation-patterns.md for full patterns for both models.

Critical rules:

  • Use || exit_code=$? to capture exit codes — never || true, which loses them
  • Some CLI tools use exit code 3 to mean "no supported project/files" (distinct from a scan error) — detect this and write a .noscan sentinel rather than retrying indefinitely
  • Use mkdir for locking (POSIX-atomic), not flock or file touches
  • Make a single jq call per cache file — multiple calls on the same file are slow
  • The script runs in Claude's cwd — use pwd / git rev-parse to find the project

Make the script executable: chmod +x statusline.sh

Configuration env vars — naming convention: Every user-tunable knob should be an env var with a sane default. Use a consistent naming prefix so vars are discoverable:

bash
# In statusline.sh — configuration block at the top
TOOL_BIN="${TOOL_BIN:-tool}" # path to the CLI binary
TOOL_STATUSLINE_TTL="${TOOL_STATUSLINE_TTL:-300}" # cache TTL in seconds
TOOL_SHOW_LOW="${TOOL_SHOW_LOW:-false}" # boolean display toggle
TOOL_SCAN_ARGS="${TOOL_SCAN_ARGS:-}" # extra args forwarded to scan command

Users can set these in their shell profile or in ~/.claude/settings.json under "env" — document both paths. The TOOL_BIN var is especially important on macOS where tools installed via nvm, fnm, rbenv, or pyenv are only in PATH in interactive shells; background subshells run by the statusline may not inherit that PATH. Always document the TOOL_BIN override and recommend pinning it if the tool is installed via a version manager:

bash
export TOOL_BIN=$(which tool) # resolve once in your shell profile

Done when: The script runs without errors from echo '{}' | ./statusline.sh in the project directory.


Step 4: Install into Claude Code

Add the statusline to ~/.claude/settings.json. The value must be an object, not a string — a plain string path will cause a settings error on startup:

json
{
"statusLine": {
"type": "command",
"command": "/absolute/path/to/statusline.sh"
}
}

Use jq to update non-destructively (preserves all other settings):

bash
jq --arg p "/absolute/path/to/statusline.sh" \
'.statusLine = {"type": "command", "command": $p}' \
~/.claude/settings.json > ~/.claude/settings.json.tmp \
&& mv ~/.claude/settings.json.tmp ~/.claude/settings.json

Done when: cat ~/.claude/settings.json shows the statusLine object with the correct absolute path.


Step 5: Create install.sh

Always create an `install.sh` in the project root. This is not optional — every statusline needs one so users can install and uninstall it without manually editing JSON. Use assets/install.sh.template as the starting point and fill in the placeholders.

A correct installer must:

  1. Use colored output — define R/GREEN/YELLOW/RED/BOLD ANSI variables and ok()/info()/die() helpers that use them; use printf not echo; print a bold tool name header at the start
  2. Check that required CLI tools are installed (with install hints if missing)
  3. Run an auth preflight — verify the tool is authenticated before touching settings
  4. Update ~/.claude/settings.json non-destructively using jq
  5. Support --remove to cleanly uninstall
  6. Print the env vars users can set to configure behavior

Auth preflight — important distinction: there are two different commands for every authenticated tool:

  • A check command (e.g. tool whoami, gh auth status) — safe to run anytime; exit 0 = authenticated
  • A do-auth command (e.g. tool auth, gh auth login) — only run this if not authenticated; on some tools re-running when already authed resets or replaces credentials

The installer should run the check command and only instruct the user to run the do-auth command if the check fails. Never silently run the auth command unconditionally.

Make it executable: chmod +x install.sh

Done when: ./install.sh runs cleanly with colored output and ./install.sh --remove cleanly removes the statusLine entry.


Step 6: Test every state

Do not rely on the live statusline alone — seed the cache manually to exercise every state:

bash
CACHE_DIR="$HOME/.cache/<tool>-statusline"
HASH=$(printf '%s' "$(git rev-parse --show-toplevel)" | cksum | cut -d' ' -f1)
# Test: clean/no issues
echo '<valid empty result JSON>' > "$CACHE_DIR/${HASH}.json"
echo '{}' | ./statusline.sh
# Test: issues found
echo '<valid result JSON with findings>' > "$CACHE_DIR/${HASH}.json"
echo '{}' | ./statusline.sh
# Test: no supported project
printf '3' > "$CACHE_DIR/${HASH}.noscan"; rm -f "$CACHE_DIR/${HASH}.json"
echo '{}' | ./statusline.sh
# Test: scanning in progress
mkdir "$CACHE_DIR/${HASH}.lock" 2>/dev/null
rm -f "$CACHE_DIR/${HASH}.json" "$CACHE_DIR/${HASH}.noscan"
echo '{}' | ./statusline.sh
rmdir "$CACHE_DIR/${HASH}.lock"
# Test: auth error
echo 'Authentication failed' > "$CACHE_DIR/${HASH}.err"
echo '{}' | ./statusline.sh

Check the raw output for correct ANSI escape codes:

bash
echo '{}' | ./statusline.sh | cat -v

^[[38;2;...m in the output means ANSI is working correctly.

Repeat testing in the project directory where the data source is valid, and in a directory where no supported files exist, to confirm the noscan path works.

Done when: All designed states produce the expected output line with correct colors and content.


Step 7: Write documentation

Create a README.md covering:

  1. What it shows — annotated output line explaining every token
  2. Why it's useful — the problem it solves for a developer, not a feature list
  3. What scans/data sources run — and why those specifically
  4. Prerequisites — tools required, accounts, authentication
  5. Quick start — clone → auth check → ./install.sh (three steps max)
  6. Manual installation — direct settings.json snippet for users who don't want the installer
  7. Uninstall — ./install.sh --remove and how to clear the cache
  8. Configuration — table of env vars with defaults, and example of setting them via settings.json "env" block
  9. Troubleshooting — how to read the error log, force a cache refresh, fix auth; include the binary PATH pinning note for tools installed via version managers

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 95 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
3
Repository forks
1
7-day trend score
7

Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/lirantal/statusline-creator-skill/statusline-creator/badge)](https://verified-skill.com/skills/lirantal/statusline-creator-skill/statusline-creator)

Something wrong with this skill or its page? Tell us.