🎨
Claude Codeのstatuslineをカスタマイズする
Claude Codeでは、カスタムスクリプトを使ってstatusline(ステータスライン)をカスタマイズできます。この記事では、Git情報やコンテキスト使用量を表示するカスタムstatuslineの設定方法を紹介します。
完成イメージ
設定後のstatuslineはこのように表示されます。

左から順に以下の情報が表示されています:
| 表示内容 | 説明 |
|---|---|
Claude 4 Opus |
使用中のモデル名(Opus以外の場合は黄色でハイライト) |
14.9K(7%) |
コンテキスト使用量(トークン数と使用率) |
~/S/zenn-contents |
現在の作業ディレクトリ(Fish shell風に短縮表示) |
main |
現在のGitブランチ |
+1 -0 |
未ステージの変更行数(追加/削除) |
設定方法
1. statusline.jsを作成
~/.claude/statusline.js にスクリプトを作成します。
~/.claude/statusline.js
#!/usr/bin/env node
const { execSync } = require("child_process");
const os = require("os");
// ANSI color codes
const c = {
reset: "\x1b[0m",
dim: "\x1b[2m",
bold: "\x1b[1m",
green: "\x1b[32m",
red: "\x1b[31m",
yellow: "\x1b[33m",
cyan: "\x1b[36m",
magenta: "\x1b[35m",
blue: "\x1b[34m",
};
// Fish-style path: /Users/username/Sandbox/my-project/node_modules → ~/S/m/node_modules
const fishPath = (fullPath) => {
const home = os.homedir();
let p = fullPath;
if (p.startsWith(home)) {
p = "~" + p.slice(home.length);
}
const parts = p.split("/");
const lastPart = parts.pop();
const abbreviated = parts.map((part) => {
if (part === "~" || part === "") return part;
return part[0];
});
abbreviated.push(lastPart);
return abbreviated.join("/");
};
// Get git branch
const getGitBranch = (cwd) => {
try {
return execSync("git branch --show-current 2>/dev/null", {
cwd,
encoding: "utf8",
stdio: ["pipe", "pipe", "pipe"],
}).trim() || null;
} catch {
return null;
}
};
// Get git diff stats (unstaged changes)
const getGitDiffStats = (cwd) => {
try {
const stats = execSync("git diff --shortstat 2>/dev/null", {
cwd,
encoding: "utf8",
stdio: ["pipe", "pipe", "pipe"],
}).trim();
if (!stats) return { added: 0, removed: 0 };
const addedMatch = stats.match(/(\d+) insertion/);
const removedMatch = stats.match(/(\d+) deletion/);
return {
added: addedMatch ? parseInt(addedMatch[1], 10) : 0,
removed: removedMatch ? parseInt(removedMatch[1], 10) : 0,
};
} catch {
return { added: 0, removed: 0 };
}
};
// Format token count
const formatTokens = (tokens) =>
tokens >= 1000000
? `${(tokens / 1000000).toFixed(1)}M`
: tokens >= 1000
? `${(tokens / 1000).toFixed(1)}K`
: tokens.toString();
// Format context usage with color
const formatContext = (contextWindow) => {
if (!contextWindow?.context_window_size) {
return `${c.dim}ctx:--${c.reset}`;
}
const size = contextWindow.context_window_size;
const usage = contextWindow.current_usage;
let usedTokens = 0;
if (usage) {
usedTokens =
(usage.input_tokens || 0) +
(usage.cache_creation_input_tokens || 0) +
(usage.cache_read_input_tokens || 0);
}
const percent = Math.round((usedTokens / size) * 100);
const tokenStr = formatTokens(usedTokens);
// Color based on usage level
let color = c.green;
if (percent >= 80) color = c.red;
else if (percent >= 60) color = c.yellow;
else if (percent >= 40) color = c.cyan;
return `${color}${tokenStr}(${percent}%)${c.reset}`;
};
// Format model name - highlight if NOT opus
const formatModel = (model) => {
if (!model) return "";
const name = model.display_name || model.id || "unknown";
const lowerName = name.toLowerCase();
// Dim if opus (expected), bold yellow if changed
if (lowerName.includes("opus")) {
return `${c.dim}${name}${c.reset}`;
}
return `${c.yellow}${c.bold}${name}${c.reset}`;
};
// Build status line
const buildStatusLine = (input) => {
try {
const data = JSON.parse(input);
const cwd = data.workspace?.current_dir || data.cwd || process.cwd();
const model = data.model;
const contextWindow = data.context_window;
// Git info
const branch = getGitBranch(cwd);
const gitStats = getGitDiffStats(cwd);
// Build parts
const parts = [];
// Model
const modelStr = formatModel(model);
if (modelStr) parts.push(modelStr);
// Context usage
parts.push(formatContext(contextWindow));
// Fish-style directory
parts.push(`${c.blue}${fishPath(cwd)}${c.reset}`);
// Git branch and stats
if (branch) {
let gitPart = `${c.magenta}${branch}${c.reset}`;
if (gitStats.added > 0 || gitStats.removed > 0) {
const statsArr = [];
if (gitStats.added > 0) {
statsArr.push(`${c.green}+${gitStats.added}${c.reset}`);
}
if (gitStats.removed > 0) {
statsArr.push(`${c.red}-${gitStats.removed}${c.reset}`);
}
gitPart += ` ${statsArr.join(" ")}`;
}
parts.push(gitPart);
}
return parts.join(" │ ");
} catch {
return `${c.dim}statusline error${c.reset}`;
}
};
// Main
const chunks = [];
process.stdin.on("data", (chunk) => chunks.push(chunk));
process.stdin.on("end", () => console.log(buildStatusLine(chunks.join(""))));
2. 実行権限を付与
chmod +x ~/.claude/statusline.js
3. settings.jsonを設定
~/.claude/settings.json にstatusLineの設定を追加します。
~/.claude/settings.json
{
"statusLine": {
"type": "command",
"command": "~/.claude/statusline.js",
"padding": 0
}
}
各機能の解説
コンテキスト使用量の色分け
使用率に応じて色が変わります:
| 使用率 | 色 |
|---|---|
| 0-39% | 緑 |
| 40-59% | シアン |
| 60-79% | 黄 |
| 80%以上 | 赤 |
コンテキストが圧迫されてきたら一目でわかるので、/clear や /compact のタイミングを判断しやすくなります。
モデル名のハイライト
通常使用するモデル(Opus)はグレーで目立たなく表示し、異なるモデルに切り替わった場合は黄色で強調表示されます。これにより、意図しないモデル変更に気づきやすくなります。
Fish shell風パス短縮
長いパスも短縮して表示されます:
-
/Users/username/Sandbox/my-project→~/S/my-project -
/Users/username/Projects/my-app/src/components→~/P/m/s/components
最後のディレクトリ名だけフルで表示し、それ以外は頭文字1文字に短縮されます。
Git情報
- ブランチ名: マゼンタで表示
-
追加行数: 緑の
+Nで表示 -
削除行数: 赤の
-Nで表示
未ステージの変更がある場合のみ差分統計が表示されます。
入力データの形式
Claude Codeはstatuslineスクリプトに以下のようなJSONデータを標準入力で渡します:
{
"workspace": {
"current_dir": "/Users/username/Projects/my-project"
},
"model": {
"display_name": "Claude 4 Opus",
"id": "claude-opus-4-5-20251101"
},
"context_window": {
"context_window_size": 200000,
"current_usage": {
"input_tokens": 14900,
"cache_creation_input_tokens": 0,
"cache_read_input_tokens": 0
}
}
}
このデータを解析して、好みの形式でstatuslineを出力できます。
カスタマイズのヒント
- 区切り文字の
│を他の文字(|,/,>など)に変更可能 - 色はANSIカラーコードで自由に変更可能
- 日時やシステム情報など、任意の情報を追加可能
- Node.js以外の言語(Python, Bash, Rustなど)でも実装可能
ぜひ自分好みのstatuslineをカスタマイズしてみてください。
Discussion