✧ ███████████▋ 73% 🗝 Ultima Weapon ✦ app ∙ main
♥ ████████████████████████ 100% 「SAVE POINT」 ✶ Limit Form ◉ 41
Weekly Quota Pacer
Per-model and all-model weekly quota meters, showing whether usage is ahead of an even pace and when the allowance resets.
Before you install
- This version was reviewed before it was listed on Oct 18, 2026
- Reads your Claude login
- Connects to api.anthropic.com
Preview
Opus · F:15% ██▍ ▏ A:7% █▏ ▏ ⟳ 3dOpus · F:15% ██▍ ▏ A:9% █▌ ▏ ⟳ 3dSonnet · F:15% ██▍ ▏ A:18% ██▉ ▏ ⟳ 3dOpus · F:15% ██▍ ▏ A:61% █████████▊ ▏ ⟳ 20hFable · F:80% █████🮕🮕🮕🮕🮕🮕🮕🮕 A:80% █████🮕🮕🮕🮕🮕🮕🮕🮕 ⟳ 5dHaiku · F:15% ██▍ ▏ A:9% █▌ ▏ ⟳ 3dOpus · F:15% ██▍ ▏ A:20% ███▎ ▏ ⟳ 2dOpus · F:15% ██▍ ▏ A:9% █▌ ▏ ⟳ 3dWhat it does
- Written in
- Node.js
- Network access
- api.anthropic.com
- Reads your Claude login
- Yes
- Works in
- Terminal
Source
#!/usr/bin/env node
// Claude Code statusline: weekly quota meters (per-model + all models) with
// even-pacing indicators. Solid fill = usage, 🮕 = spent ahead of pace,
// ▏ = pace point when behind it, ⟳ Nd = weekly reset countdown.
//
// Install: save to ~/.claude/statusline-quota.js, then in ~/.claude/settings.json:
// "statusLine": { "type": "command", "command": "node ~/.claude/statusline-quota.js" }
//
// Reads your Claude Code OAuth token locally (macOS Keychain or
// ~/.claude/.credentials.json) and calls only api.anthropic.com/api/oauth/usage
// (the endpoint /usage uses; undocumented, may change). Needs Node 18+ and a
// font with Symbols for Legacy Computing (else swap 🮕 for ▒).
const fs = require("fs");
const os = require("os");
const path = require("path");
const { execFileSync } = require("child_process");
const CACHE_FILE = path.join(os.homedir(), ".claude", ".statusline-usage-cache.json");
const CACHE_TTL_MS = 60_000;
const WEEK_MS = 7 * 24 * 60 * 60 * 1000;
const BAR_WIDTH = 16;
const ESC = "\x1b[";
const RESET = ESC + "0m";
const DIM = ESC + "2m";
const BOLD = ESC + "1m";
// Solid fill in the bar's identity color on a dark track
const FG_PURPLE = "38;5;141m"; // Fable
const FG_BLUE = "38;5;75m"; // All models
const BG_TRACK = ESC + "48;5;236m";
const FG_MUTED = ESC + "38;5;245m";
function readStdin() {
try {
return JSON.parse(fs.readFileSync(0, "utf8"));
} catch {
return {};
}
}
function getToken() {
try {
const raw = execFileSync(
"security",
["find-generic-password", "-s", "Claude Code-credentials", "-w"],
{ encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }
);
const tok = JSON.parse(raw).claudeAiOauth?.accessToken;
if (tok) return tok;
} catch {}
try {
const raw = fs.readFileSync(path.join(os.homedir(), ".claude", ".credentials.json"), "utf8");
return JSON.parse(raw).claudeAiOauth?.accessToken || null;
} catch {}
return null;
}
function readCache() {
try {
return JSON.parse(fs.readFileSync(CACHE_FILE, "utf8"));
} catch {
return null;
}
}
async function getUsage() {
const cache = readCache();
if (cache && Date.now() - cache.fetchedAt < CACHE_TTL_MS) return cache.data;
const token = getToken();
if (!token) return cache?.data ?? null;
try {
const ctl = new AbortController();
const timer = setTimeout(() => ctl.abort(), 3000);
const res = await fetch("https://api.anthropic.com/api/oauth/usage", {
headers: {
Authorization: `Bearer ${token}`,
"anthropic-beta": "oauth-2025-04-20",
"Content-Type": "application/json",
},
signal: ctl.signal,
});
clearTimeout(timer);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data = await res.json();
fs.writeFileSync(CACHE_FILE, JSON.stringify({ fetchedAt: Date.now(), data }));
return data;
} catch {
return cache?.data ?? null; // stale is better than nothing
}
}
function pacePercent(resetsAt) {
const reset = Date.parse(resetsAt);
if (Number.isNaN(reset)) return null;
const start = reset - WEEK_MS;
return Math.min(100, Math.max(0, ((Date.now() - start) / WEEK_MS) * 100));
}
// Bar with the percent embedded: fill = actual usage (background color),
// white '│' = where even weekly pacing would put you, drawn over fill or track.
function segment(label, used, resetsAt, identityFg) {
const pace = pacePercent(resetsAt);
const fillFg = ESC + identityFg;
// Pace is shown one of two ways, so any two-tone fill is intentional:
// - behind pace: normal '▒' fill, thin '▏' hairline out in the track at
// the pace position
// - ahead of pace: no hairline; fill cells past the pace point render as
// denser '▓' to mark the overage
const EIGHTHS = ["", "▏", "▎", "▍", "▌", "▋", "▊", "▉"];
const used8 = Math.round((used / 100) * BAR_WIDTH * 8);
const ahead = pace !== null && used > pace;
let paceCell =
pace === null ? -1 : Math.min(BAR_WIDTH - 1, Math.round((pace / 100) * BAR_WIDTH));
// Behind pace: eighth-precision edge glyph. Ahead of pace: whole cells only,
// with at least the final fill cell textured '▚' so overage is always visible.
let fullCells, rem, edgeCell;
if (ahead) {
fullCells = Math.max(1, Math.round(used8 / 8));
rem = 0;
edgeCell = -1;
if (paceCell >= fullCells) paceCell = fullCells - 1;
} else {
fullCells = Math.floor(used8 / 8);
rem = used8 % 8;
edgeCell = rem > 0 ? fullCells : -1;
}
let markerCell = -1;
if (pace !== null && !ahead) {
// '▏' marks the LEFT boundary of its cell; keep it at/past the fill edge
markerCell = paceCell;
while (markerCell < BAR_WIDTH - 1 && markerCell * 8 < used8) markerCell++;
}
let out = "";
for (let i = 0; i < BAR_WIDTH; i++) {
if (i === markerCell && i !== edgeCell) {
out += BG_TRACK + ESC + "38;5;240m" + "▏" + RESET;
} else if (i < fullCells) {
// Overage cells use '🮕' (U+1FB95 CHECKER BOARD FILL) — a fine
// full-bleed checker texture from Symbols for Legacy Computing
if (ahead && i >= paceCell) out += BG_TRACK + fillFg + "🮕" + RESET;
else out += BG_TRACK + fillFg + "█" + RESET;
} else if (i === edgeCell) {
out += BG_TRACK + fillFg + EIGHTHS[rem] + RESET;
} else {
out += BG_TRACK + " " + RESET;
}
}
return `${DIM}${label}:${RESET}${FG_MUTED}${Math.round(used)}%${RESET} ${out}`;
}
async function main() {
const input = readStdin();
try {
fs.writeFileSync(
path.join(os.homedir(), ".claude", ".statusline-last-input.json"),
JSON.stringify(input, null, 2)
);
} catch {}
const model = input.model?.display_name || "";
const usage = await getUsage();
const parts = [];
// Family name only ("Fable 5" -> "Fable") to save characters
const family = model.split(/[\s\d]/)[0];
if (family) parts.push(`${DIM}${family} ·${RESET}`);
if (!usage?.limits) {
parts.push(`${DIM}quota unavailable${RESET}`);
} else {
const weeklyAll = usage.limits.find((l) => l.kind === "weekly_all");
const scoped = usage.limits.filter((l) => l.kind === "weekly_scoped");
for (const lim of scoped) {
const label = (lim.scope?.model?.display_name || "S")[0].toUpperCase();
parts.push(segment(label, lim.percent, lim.resets_at, FG_PURPLE));
}
if (weeklyAll)
parts.push(segment("A", weeklyAll.percent, weeklyAll.resets_at, FG_BLUE));
if (!scoped.length && !weeklyAll) parts.push(`${DIM}no weekly limits reported${RESET}`);
const resetsAt = weeklyAll?.resets_at || scoped[0]?.resets_at;
const resetMs = resetsAt ? Date.parse(resetsAt) - Date.now() : NaN;
if (!Number.isNaN(resetMs) && resetMs > 0) {
let left;
if (resetMs >= 24 * 60 * 60 * 1000) left = `${Math.ceil(resetMs / 86_400_000)}d`;
else if (resetMs >= 60 * 60 * 1000) left = `${Math.ceil(resetMs / 3_600_000)}h`;
else left = `${Math.ceil(resetMs / 60_000)}m`;
parts.push(`${DIM}⟳ ${left}${RESET}`);
}
}
process.stdout.write(parts.join(" "));
}
main();
Badge for your README
Own this listing? Add it to your README. The badge shows the install count as it grows.
[](https://staging.statuslin.es/c/weekly-quota-pacer-57a36566?utm_source=readme-badge)
Or show the preview card:

[](https://staging.statuslin.es/c/weekly-quota-pacer-57a36566?utm_source=readme-badge)
More status lines
✳ Usage 5h 26% · week 7% · fable 15%
🤖 Opus 4.8 [200K] │ 🎯 high │ 📁 app │ 🌿 main
📅 07/07/26 Tue │ ⏰ 22:59:15 │ ₿$63k │ ☀️ +90°F
Ctx: ● ▓▓░░░░ 33% [66K/200K] │ ⏱ 10m │ 🔧 2.1.155
[Opus 5.5] 📁 app | 🌿 main | $0.41 | ⏱️ 10m 12s
❤️❤️❤️❤️❤️❤️❤️🖤🖤🖤 26% 2h6m 🍗🍗🍗🍗🍗🍗🍗🍗🍗🦴 7% 2d0h
🟩🟩🟩🟩🟩⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛ 22%
┌─────────────────────────────────────────────────────────────────────────────────┬────────────────────────────────┐
│ 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 | app main | ctx 22% | ▶ Fix lease reclaim
Related mods
⎿ agent-profiler: Agent Profiler pane opened (shown in the terminal and the desktop app).
╭────────────────────────────────────────────────────────────────────────────────────────────────✕─╮
│ 255ms agent time · 1 turn(s) │
│ model ███████░░░░░░░░░░░░░ 33% │
│ tools ░░░░░░░░░░░░░░░░░░░░ 0% │
│ subagents ░░░░░░░░░░░░░░░░░░░░ 0% │
│ engine/other █████████████░░░░░░░ 67% │
│ │
│ Running │
│ idle │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
⚠ agent-profiler: ⏱ model 33% · tools 0%Execution profiler for Claude Code: model wait vs tools vs subagents, live, with OTLP export

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.

Browse the reviewed mods on statuslin.es in a pane, with their install counts and what each can reach, and put one's install prompt in your prompt box. /gallery opens it. It runs nothing: you read the prompt and send it.
[-]
▄▄▄▀▀▀▀▀▄▄▄
▀ ▀ ▀▀
▀ ▀▄
▀▀▀▀ ▀▀▀▀
▀▀▀▀▀▀▀▀▀▀▀
▄▀▀▀ ▀▀▀ ▀▀▄▄ Lv 5
▀▀ ▀▀▀ ▀▀▀▀▀▀ ●●●●○
▀▀ ▀▀ ♥♥♥♥♡A pixel Pokémon that lives at the right edge of the band above the prompt