╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ▐ Opus 4.8 ▌ ▐ high ▌ ▐ …/user/app ▌ ▐ main ▌ ▐ 22% / 200k ━━━━━━━━━━ ▌ ▐ 26% ━━━━━━━━━━ 16:10 ▌ ▐ +128 −34 ▌ ▐ $0.41 ▌ ▐ 10m 12s ▌ │
│ MODEL EFFORT PATH BRANCH CONTEXT USAGE DIFF COST TIME │
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
Minecraft Bars
Three Minecraft-style lines: the model tinted by material (netherite, diamond, gold or iron), folder, git branch, cost and session time; hearts for five-hour usage and drumsticks for seven-day usage, emptying as they climb, with reset countdowns; then an XP bar for the context window. Node built-ins only, no network calls.
In Claude Desktop? This status line shows there once you also install statusline-anywhere.
Before you install
- This version was reviewed before it was listed on Nov 2, 2026
- Doesn't ask to connect to the internet
- Runs git through execSync with fixed commands and no timeout. It writes no files and reads no credentials.
- Never shows cache tokens. It reads them from cost, where Claude Code doesn't send them.
- The hearts and drumsticks row stays blank until Claude Code sends rate limits.
Preview
[Opus 5.5] 📁 app | 🌿 main | $0.41 | ⏱️ 10m 12s
❤️❤️❤️❤️❤️❤️❤️🖤🖤🖤 26% 2h6m 🍗🍗🍗🍗🍗🍗🍗🍗🍗🦴 7% 2d0h
🟩🟩🟩🟩🟩⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛ 22%
[Opus 5.5] 📁 app | 🌿 main | $0.00 | ⏱️ 10m 12s
⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛ 0%
[Sonnet 5.5] 📁 app | 🌿 feat/auth! | $0.41 | ⏱️ 10m 12s
❤️❤️❤️❤️❤️❤️🖤🖤🖤🖤 40% 1h11m 🍗🍗🍗🍗🍗🍗🍗🍗🦴🦴 18% 2d21h
🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛ 48%
[Opus 5.5] 📁 app | 🌿 main | $4.12 | ⏱️ 10m 12s
❤️🖤🖤🖤🖤🖤🖤🖤🖤🖤 88% 17m 🍗🍗🍗🍗🦴🦴🦴🦴🦴🦴 61% 19h59m
🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩⬛⬛⬛ 91%
[Fable 5.1] 📁 app | 🌿 main | $0.41 | ⏱️ 10m 12s
❤️❤️❤️❤️❤️❤️❤️🖤🖤🖤 33% 3h29m 🍗🍗🦴🦴🦴🦴🦴🦴🦴🦴 80% 4d23h
🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛ 64%
[Haiku 4.5] 📁 app | 🌿 main | $0.41 | ⏱️ 10m 12s
❤️❤️❤️❤️❤️🖤🖤🖤🖤🖤 52% 4h1m
⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛ 0%
[Opus 5.5] 📁 feature | 🌿 worktree-feature | $0.41 | ⏱️ 10m 12s
🟩🟩🟩🟩🟩🟩🟩🟩🟩⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛ 37%
[Opus 5.5] 📁 scratch | $0.41 | ⏱️ 10m 12s
🟩🟩🟩🟩🟩⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛ 22%
What it does
A Minecraft status line for Claude Code on three lines. Model, folder, git branch, cost and time on top, hearts and drumsticks for your rate limits, then an XP bar for context.
- Written in
- Node.js
- Network access
- None requested
- Works in
- Terminal
How it works
- Reads model, folder, cost, session time, context use and both rate limits from stdin.
- Tints the model by material: netherite for Fable, diamond for Opus, gold for Sonnet.
- Hearts drain with five-hour usage and drumsticks with seven-day usage, with reset timers.
- A 26-square XP bar fills with context. A branch gets * if staged, ! for other edits.
Source
#!/usr/bin/env node
// minecraft-statusline — a Minecraft-themed statusline for Claude Code
// https://github.com/jonahmabry/minecraft-statusline
//
// Line 1: model (tinted by "material" — netherite/diamond/gold/iron), dir, git branch, cost, elapsed time, cache tokens
// Line 2: hearts = 5-hour rate limit (depletes as usage climbs), food = 7-day rate limit
// Line 3: XP bar = context window fill percentage
//
// Pure Node — no external dependencies. git is optional (used only for the branch segment).
const { execSync } = require("child_process");
const NETHERITE = "\x1b[0;90m";
const DIAMOND = "\x1b[96m";
const GOLD = "\x1b[1;33m";
const IRON = "\x1b[38;5;251m";
const CYAN = "\x1b[36m";
const MAGENTA = "\x1b[35m";
const RESET = "\x1b[0m";
// ---------- helpers ----------
// Integer part of a possibly-decimal value ("42.5" -> 42), mirroring bash ${x%.*}.
function intPart(v) {
const n = parseInt(String(v), 10);
return Number.isNaN(n) ? 0 : n;
}
function formatCountdown(resetsAt) {
const now = Math.floor(Date.now() / 1000);
const diff = Number(resetsAt) - now;
if (diff <= 0) return "now";
if (diff < 3600) return `${Math.floor(diff / 60)}m`;
if (diff < 86400) return `${Math.floor(diff / 3600)}h${Math.floor((diff % 3600) / 60)}m`;
return `${Math.floor(diff / 86400)}d${Math.floor((diff % 86400) / 3600)}h`;
}
// 10-icon bar that DEPLETES as usage climbs.
function renderMcBar(used, full, empty) {
let remaining = 100 - intPart(used);
if (remaining < 0) remaining = 0;
if (remaining > 100) remaining = 100;
let filled = Math.floor((remaining + 5) / 10);
if (filled > 10) filled = 10;
if (filled === 0 && remaining > 0) filled = 1;
const empties = 10 - filled;
return full.repeat(filled) + empty.repeat(empties);
}
// N-segment bar that FILLS as usage climbs.
function renderFillBar(pct, full, empty, segs) {
let filled = Math.floor((pct * segs) / 100);
if (filled > segs) filled = segs;
const empties = segs - filled;
return full.repeat(filled) + empty.repeat(empties);
}
function fmtTokens(n) {
n = Number(n) || 0;
return n >= 1000 ? `${Math.floor(n / 1000)}k` : `${n}`;
}
// Present = value provided and non-empty, mirroring bash `// empty` + [ -n ] (0 counts as present).
function present(v) {
return v !== undefined && v !== null && v !== "";
}
function gitBranch(dir) {
if (!dir) return "";
const run = (cmd) => execSync(cmd, { cwd: dir, stdio: ["ignore", "pipe", "ignore"] }).toString();
try {
run("git rev-parse --git-dir");
} catch {
return "";
}
let branchName = "";
try {
branchName = run("git branch --show-current").trim();
} catch {
/* detached HEAD or no commits — leave blank */
}
let dirty = "";
try {
const lines = run("git status --porcelain").split("\n").filter((l) => l.length > 0);
if (lines.length > 0) {
// A staged/changed index char (not space, not ?) means dirty "*"; otherwise "!".
dirty = lines.some((l) => l[0] !== " " && l[0] !== "?") ? "*" : "!";
}
} catch {
/* ignore */
}
return ` | 🌿 ${branchName}${dirty}`;
}
function render(input) {
let data;
try {
data = JSON.parse(input);
} catch {
return; // no/!invalid input — print nothing rather than a broken line
}
const model = data?.model?.display_name ?? "";
const dir = data?.workspace?.current_dir ?? "";
const cost = Number(data?.cost?.total_cost_usd ?? 0);
const pct = intPart(data?.context_window?.used_percentage ?? 0);
const durationMs = Number(data?.cost?.total_duration_ms ?? 0);
const cacheRead = Number(data?.cost?.cache_read_input_tokens ?? 0);
const cacheWrite = Number(data?.cost?.cache_creation_input_tokens ?? 0);
// ---------- model color (tints the model name in the header) ----------
const modelLc = model.toLowerCase();
let modelColor = IRON;
if (modelLc.includes("fable")) modelColor = NETHERITE;
else if (modelLc.includes("opus")) modelColor = DIAMOND;
else if (modelLc.includes("sonnet")) modelColor = GOLD;
else if (modelLc.includes("haiku")) modelColor = IRON;
// ---------- XP bar = context window (fills up as the window fills) ----------
const xpBar = renderFillBar(pct, "🟩", "⬛", 26);
// ---------- elapsed time ----------
const mins = Math.floor(durationMs / 60000);
const secs = Math.floor((durationMs % 60000) / 1000);
const timeFmt = `⏱️ ${mins}m ${secs}s`;
// ---------- git branch ----------
const branch = gitBranch(dir);
// ---------- rate limits: hearts = 5h, food = 7d ----------
const fivePct = data?.rate_limits?.five_hour?.used_percentage;
const fiveResets = data?.rate_limits?.five_hour?.resets_at;
const weekPct = data?.rate_limits?.seven_day?.used_percentage;
const weekResets = data?.rate_limits?.seven_day?.resets_at;
let healthSeg = "";
if (present(fivePct)) {
healthSeg = `${renderMcBar(fivePct, "❤️", "🖤")} ${intPart(fivePct)}%`;
if (present(fiveResets)) healthSeg += ` ${MAGENTA}${formatCountdown(fiveResets)}${RESET}`;
}
let foodSeg = "";
if (present(weekPct)) {
foodSeg = `${renderMcBar(weekPct, "🍗", "🦴")} ${intPart(weekPct)}%`;
if (present(weekResets)) foodSeg += ` ${MAGENTA}${formatCountdown(weekResets)}${RESET}`;
}
// ---------- cost + cache ----------
const costFmt = `$${cost.toFixed(2)}`;
let cacheSegment = "";
if (cacheRead > 0 || cacheWrite > 0) {
cacheSegment = ` | ${CYAN}↩${fmtTokens(cacheRead)} ↪${fmtTokens(cacheWrite)}${RESET}`;
}
// ---------- render the HUD ----------
const dirBase = String(dir).split(/[/\\]/).pop();
const line1 = `${modelColor}[${model}]${RESET} 📁 ${dirBase}${branch} | ${GOLD}${costFmt}${RESET} | ${timeFmt}${cacheSegment}`;
const line2 = `${healthSeg} ${foodSeg}`;
const line3 = `${xpBar} ${pct}%`;
process.stdout.write(`${line1}\n${line2}\n${line3}\n`);
}
let input = "";
process.stdin.setEncoding("utf8");
process.stdin.on("data", (chunk) => (input += chunk));
process.stdin.on("end", () => render(input));
More status lines
┌─────────────────────────────────────────────────────────────────────────────────┬────────────────────────────────┐
│ session summary session b8e1c0d2 │ │
├──────────────────────────┬──────────────────────────────────────────────────────┤ │
│ 📁 user/app +0 -0 lines │ Opus 5.5 effort high · 0min │ │
│ app main │ cost $0.00 (all time) · $0.00 (this session) │ │
├──────────────────────────┴──────────────────────────────────────────────────────┤ │
│ tokens 0 (all time) · 0 (this session) context ██░░░░░░░░ 22% compact 0 times │ │
├─────────────────────────────────────────────────────────────────────────────────┤ │
│ 5h-quota ███░░░░░░░ 26% resets 2h6m 7d-quota █░░░░░░░░░ 7% resets 2d0h │ │
└─────────────────────────────────────────────────────────────────────────────────┴────────────────────────────────┘Opus 4.8 [high] ~/app main
16:20:55 | ⛁ ██░░░░░░░░ 22% | 5h ●◔○○○ 26% ↻2h7m | 7d ◔○○○○○○ 7% ↻2d1h │ $0.41 ⏱ 10m
Opus 4.8 high ✦ │ ctx 22% │ app (main) │ PR #1287 ● │ $0.41 · 10m +128 -34
Session ● ● ● ● ● ● ● ● ○ ○ ○ 74% left Resets in 2h 6m
Weekly ● ● ● ● ● ● ● ● ● ● ○ 93% left Resets in 2d 0h
Fable ● ● ● ● ● ● ● ● ● ○ ○ 85% left Resets in 2d 0h
◐ Read:index.ts ✓ Read×1 ✓ Bash×1 ✓ Edit×1 ✓ Grep×1
◐ code-reviewer Review the change for regressions
Model: Opus 4.8 | Thinking: high | Context: [▰▰▱▱▱▱▱▱▱▱] 45k/200k (22%) | cwd: ~/app | ⎇ main | (+0,-0)
Cost: $0.41 | Block: 2hr 6m | Weekly: 7.0% | Session: 10m | In: 916.7 t/s | Out: 29.2 t/s | Cached: 2k | Session: [▰▱▱▱▱] 26.0%
Mem: 0.8G/1.0G | (*゚∀゚*) | Session ID: b8e1c0d2-4a6f-4e2a-9c1b-3f5d7a9e2c10
app · main · Opus 4.8 · high
ctx 22% 44k · 5h 26% ↻2h6m · 7d 7% ↻2d0h · cost $0.41 · msg $0.757Related mods

A cockpit for Claude Code: plan bars and subagent strips, context, usage limits with reset countdowns and burn rates, spend, the model route and a pet. Six bar styles, three collapsed looks. CLI and Desktop.

An animated pixel-art companion above your prompt that reacts to your session and your typing, with a live context meter.
Shows branch safety, context headroom, and account usage in a compact session telemetry strip

One line above the prompt: context tokens with their weather, a bar per recent prompt, your 5-hour and 7-day limits against the time elapsed, the prompt cache with its time left, the session cost with the last prompt's share in dollars and in points of the 5-hour limit, and the subagents running. Labels in English, French or Russian. After Token Weather (Anthropic, Apache-2.0) and the ideas of usage-meter (HolyGrail) and prompt-cache-control (Daniel San).