> ## Documentation Index
> Fetch the complete documentation index at: https://code.claude.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# 自訂您的狀態列

> 設定自訂狀態列以監控 Claude Code 中的 context window 使用情況、成本和 git 狀態

狀態列是 Claude Code 底部的可自訂列，可執行您設定的任何 shell 指令碼。它透過 stdin 接收 JSON 工作階段資料，並顯示您的指令碼列印的任何內容，為您提供 context 使用情況、成本、git 狀態或任何其他您想追蹤的內容的持久、一目瞭然的檢視。

狀態列在以下情況下很有用：

* 您想在工作時監控 context window 使用情況
* 您需要追蹤工作階段成本
* 您跨多個工作階段工作，需要區分它們
* 您希望 git 分支和狀態始終可見

狀態列會在內建頁尾徽章上方的自己的列中呈現，不會取代它們。若要在對話中出現 ID 時在頁尾新增可點擊的連結徽章，而不需要撰寫指令碼，請改為設定 [`footerLinksRegexes`](/zh-TW/settings#footer-link-badges)。

以下是一個[多行狀態列](#display-multiple-lines)的範例，在第一行顯示 git 資訊，在第二行顯示顏色編碼的 context 列。

<Frame>
  <img src="https://mintcdn.com/claude-code/nibzesLaJVh4ydOq/images/statusline-multiline.png?fit=max&auto=format&n=nibzesLaJVh4ydOq&q=85&s=60f11387658acc9ff75158ae85f2ac87" alt="多行狀態列，在第一行顯示模型名稱、目錄、git 分支，在第二行顯示 context 使用進度列、成本和持續時間" width="776" height="212" data-path="images/statusline-multiline.png" />
</Frame>

本頁面介紹[設定基本狀態列](#set-up-a-status-line)、說明[資料如何從 Claude Code 流向您的指令碼](#how-status-lines-work)、列出[您可以顯示的所有欄位](#available-data)，並提供[常見模式的現成範例](#examples)，例如 git 狀態、成本追蹤和進度列。

<h2 id="set-up-a-status-line">
  設定狀態列
</h2>

使用[`/statusline` 命令](#use-the-%2Fstatusline-command)讓 Claude Code 為您產生指令碼，或[手動建立指令碼](#manually-configure-a-status-line)並將其新增到您的設定。

<h3 id="use-the-/statusline-command">
  使用 /statusline 命令
</h3>

`/statusline` 命令接受描述您想顯示內容的自然語言指令。Claude Code 在 `~/.claude/` 中產生指令碼檔案並自動更新您的設定：

```text theme={null}
/statusline show model name and context percentage with a progress bar
```

<h3 id="manually-configure-a-status-line">
  手動設定狀態列
</h3>

將 `statusLine` 欄位新增到您的使用者設定（`~/.claude/settings.json`，其中 `~` 是您的主目錄）或[專案設定](/zh-TW/settings#settings-files)。將 `type` 設定為 `"command"`，並將 `command` 指向指令碼路徑或內聯 shell 命令。如需建立指令碼的完整逐步說明，請參閱[逐步建立狀態列](#build-a-status-line-step-by-step)。

```json theme={null}
{
  "statusLine": {
    "type": "command",
    "command": "~/.claude/statusline.sh",
    "padding": 2
  }
}
```

`command` 欄位在 shell 中執行，因此您也可以使用內聯命令而不是指令碼檔案。此範例使用 `jq` 解析 JSON 輸入並顯示模型名稱和 context 百分比：

```json theme={null}
{
  "statusLine": {
    "type": "command",
    "command": "jq -r '\"[\\(.model.display_name)] \\(.context_window.used_percentage // 0)% context\"'"
  }
}
```

可選的 `padding` 欄位為狀態列內容新增額外的水平間距（以字元為單位）。預設為 `0`。此填充是在介面的內建間距之外，因此它控制相對縮排而不是距離終端邊緣的絕對距離。

可選的 `refreshInterval` 欄位除了[事件驅動的更新](#how-status-lines-work)外，每 N 秒重新執行一次您的命令。最小值為 `1`。當您的狀態列顯示基於時間的資料（例如時鐘）或背景子代理在主工作階段閒置時變更 git 狀態時，請設定此項。保持未設定以僅在事件上執行。

可選的 `hideVimModeIndicator` 欄位會隱藏提示下方的內建 `-- INSERT --` 文字。當您的指令碼自行呈現 [`vim.mode`](#available-data) 時，請將此設定為 `true`，以便模式不會顯示兩次。

<h3 id="disable-the-status-line">
  停用狀態列
</h3>

執行 `/statusline` 並要求它移除或清除您的狀態列（例如 `/statusline delete`、`/statusline clear`、`/statusline remove it`）。您也可以手動從 settings.json 中刪除 `statusLine` 欄位。

<h2 id="build-a-status-line-step-by-step">
  逐步建立狀態列
</h2>

此逐步說明透過手動建立顯示目前模型、工作目錄和 context window 使用百分比的狀態列來展示幕後發生的情況。

<Note>使用 [`/statusline`](#use-the-%2Fstatusline-command) 和您想要的內容描述會自動為您設定所有這些。</Note>

這些範例使用 Bash 指令碼，適用於 macOS 和 Linux。在 Windows 上，請參閱 [Windows 設定](#windows-configuration)以取得 PowerShell 和 Git Bash 範例。

<Frame>
  <img src="https://mintcdn.com/claude-code/nibzesLaJVh4ydOq/images/statusline-quickstart.png?fit=max&auto=format&n=nibzesLaJVh4ydOq&q=85&s=696445e59ca0059213250651ad23db6b" alt="狀態列顯示模型名稱、目錄和 context 百分比" width="726" height="164" data-path="images/statusline-quickstart.png" />
</Frame>

<Steps>
  <Step title="建立讀取 JSON 並列印輸出的指令碼">
    Claude Code 透過 stdin 將 JSON 資料傳送到您的指令碼。此指令碼使用 [`jq`](https://jqlang.github.io/jq/)（一個您可能需要安裝的命令列 JSON 解析器）來提取模型名稱、目錄和 context 百分比，然後列印格式化的行。

    將此儲存到 `~/.claude/statusline.sh`（其中 `~` 是您的主目錄，例如 macOS 上的 `/Users/username` 或 Linux 上的 `/home/username`）：

    ```bash theme={null}
    #!/bin/bash
    # Read JSON data that Claude Code sends to stdin
    input=$(cat)

    # Extract fields using jq
    MODEL=$(echo "$input" | jq -r '.model.display_name')
    DIR=$(echo "$input" | jq -r '.workspace.current_dir')
    # The "// 0" provides a fallback if the field is null
    PCT=$(echo "$input" | jq -r '.context_window.used_percentage // 0' | cut -d. -f1)

    # Output the status line - ${DIR##*/} extracts just the folder name
    echo "[$MODEL] 📁 ${DIR##*/} | ${PCT}% context"
    ```
  </Step>

  <Step title="使其可執行">
    將指令碼標記為可執行，以便您的 shell 可以執行它：

    ```bash theme={null}
    chmod +x ~/.claude/statusline.sh
    ```
  </Step>

  <Step title="新增到設定">
    告訴 Claude Code 執行您的指令碼作為狀態列。將此設定新增到 `~/.claude/settings.json`，它將 `type` 設定為 `"command"`（意思是「執行此 shell 命令」）並將 `command` 指向您的指令碼：

    ```json theme={null}
    {
      "statusLine": {
        "type": "command",
        "command": "~/.claude/statusline.sh"
      }
    }
    ```

    您的狀態列出現在介面底部。設定會自動重新載入，但變更在您與 Claude Code 的下一次互動之前不會出現。
  </Step>
</Steps>

<h2 id="how-status-lines-work">
  狀態列如何運作
</h2>

Claude Code 執行您的指令碼並透過 stdin 將 [JSON 工作階段資料](#available-data) 傳送給它。您的指令碼讀取 JSON、提取所需內容並將文字列印到 stdout。Claude Code 顯示您的指令碼列印的任何內容。

**何時更新**

您的指令碼在每個新的助手訊息之後、`/compact` 完成後、權限模式變更時或 vim 模式切換時執行。更新在 300ms 處進行去抖動，這意味著快速變更會批次在一起，您的指令碼在事情穩定後執行一次。如果在您的指令碼仍在執行時觸發新的更新，則會取消進行中的執行。如果您編輯指令碼，變更在您與 Claude Code 的下一次互動觸發更新之前不會出現。

這些觸發器在主工作階段閒置時可能會安靜，例如當協調器等待背景子代理時。為了在閒置期間保持基於時間或外部來源的片段最新，請將 [`refreshInterval`](#manually-configure-a-status-line) 設定為也在固定計時器上重新執行命令。

**您的指令碼可以輸出什麼**

* **多行**：每個 `echo` 或 `print` 陳述式顯示為單獨的行。請參閱[多行範例](#display-multiple-lines)。
* **顏色**：使用 [ANSI 逃逸碼](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors)，例如 `\033[32m` 表示綠色（終端必須支援它們）。請參閱 [git 狀態範例](#git-status-with-colors)。
* **連結**：使用 [OSC 8 逃逸序列](https://en.wikipedia.org/wiki/ANSI_escape_code#OSC) 使文字可點擊（macOS 上為 Cmd+click，Windows/Linux 上為 Ctrl+click）。需要支援超連結的終端，例如 iTerm2、Kitty 或 WezTerm。請參閱[可點擊連結範例](#clickable-links)。

**調整輸出大小以適應終端**

Claude Code 會擷取您指令碼的輸出，而不是直接將其連接到終端，因此 `tput cols` 和語言層級的寬度偵測無法從指令碼內部讀取終端大小。{/* min-version: 2.1.153 */}改為讀取 `COLUMNS` 和 `LINES` 環境變數。Claude Code 在執行您的指令碼之前會將這些設定為目前的終端尺寸。需要 Claude Code v2.1.153 或更新版本。

<Note>狀態列在本地執行，不消耗 API 令牌。在某些 UI 互動期間，它會暫時隱藏，包括自動完成建議、說明功能表和權限提示。</Note>

<h2 id="available-data">
  可用資料
</h2>

Claude Code 透過 stdin 將以下 JSON 欄位傳送到您的指令碼：

| 欄位                                                                               | 描述                                                                                                                                                                                         |
| -------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `model.id`, `model.display_name`                                                 | 目前的模型識別碼和顯示名稱                                                                                                                                                                              |
| `cwd`, `workspace.current_dir`                                                   | 目前的工作目錄。兩個欄位包含相同的值；`workspace.current_dir` 因與 `workspace.project_dir` 一致而首選。                                                                                                               |
| `workspace.project_dir`                                                          | 啟動 Claude Code 的目錄，如果工作階段期間工作目錄變更，可能與 `cwd` 不同                                                                                                                                             |
| `workspace.added_dirs`                                                           | 透過 `/add-dir` 或 `--add-dir` 新增的其他目錄。如果未新增任何目錄，則為空陣列                                                                                                                                        |
| `workspace.git_worktree`                                                         | 當目前目錄位於使用 `git worktree add` 建立的連結 worktree 內時的 Git worktree 名稱。在主工作樹中不存在。對任何 git worktree 都會填入，不同於 `worktree.*` 僅適用於 `--worktree` 工作階段                                                    |
| `workspace.repo.host`, `workspace.repo.owner`, `workspace.repo.name`             | 從 `origin` 遠端解析的儲存庫身分，例如 `"github.com"`、`"anthropics"`、`"claude-code"`。在 git 儲存庫外或未設定 `origin` 遠端時不存在                                                                                      |
| `cost.total_cost_usd`                                                            | 工作階段總成本（美元），在用戶端計算。可能與您的實際帳單不同                                                                                                                                                             |
| `cost.total_duration_ms`                                                         | 自工作階段開始以來的總掛鐘時間（毫秒）                                                                                                                                                                        |
| `cost.total_api_duration_ms`                                                     | 等待 API 回應所花費的總時間（毫秒）                                                                                                                                                                       |
| `cost.total_lines_added`, `cost.total_lines_removed`                             | 變更的程式碼行數                                                                                                                                                                                   |
| `context_window.total_input_tokens`, `context_window.total_output_tokens`        | 目前在 context window 中的令牌計數，來自最近的 API 回應。輸入包括快取讀取和寫入。{/* min-version: 2.1.132 */}v2.1.132 之前這些是累積工作階段總計                                                                                      |
| `context_window.context_window_size`                                             | 最大 context window 大小（令牌）。預設為 200000，或具有擴展 context 的模型為 1000000。                                                                                                                            |
| `context_window.used_percentage`                                                 | 預先計算的已使用 context window 百分比                                                                                                                                                                |
| `context_window.remaining_percentage`                                            | 預先計算的剩餘 context window 百分比                                                                                                                                                                 |
| `context_window.current_usage`                                                   | 最後一次 API 呼叫中的令牌計數，在 [context window 欄位](#context-window-fields)中描述                                                                                                                         |
| `exceeds_200k_tokens`                                                            | 最近 API 回應中的總令牌計數（輸入、快取和輸出令牌合併）是否超過 200k。這是一個固定閾值，與實際 context window 大小無關。                                                                                                                  |
| `effort.level`                                                                   | 目前的推理努力等級（`low`、`medium`、`high`、`xhigh` 或 `max`）。反映即時工作階段值，包括工作階段中途的 `/effort` 變更。Ultracode 不是一個不同的等級，報告為 `xhigh`。當目前模型不支援努力參數時不存在                                                         |
| `thinking.enabled`                                                               | 是否為工作階段啟用擴展思考                                                                                                                                                                              |
| `rate_limits.five_hour.used_percentage`, `rate_limits.seven_day.used_percentage` | 消耗的 5 小時或 7 天速率限制的百分比，從 0 到 100                                                                                                                                                            |
| `rate_limits.five_hour.resets_at`, `rate_limits.seven_day.resets_at`             | 5 小時或 7 天速率限制視窗重設時的 Unix 紀元秒數                                                                                                                                                              |
| `session_id`                                                                     | 唯一的工作階段識別碼                                                                                                                                                                                 |
| `session_name`                                                                   | 使用 `--name` 旗標或 `/rename` 設定的自訂工作階段名稱。如果未設定自訂名稱，則不存在                                                                                                                                       |
| `prompt_id`                                                                      | 識別目前正在處理的使用者提示的 UUID。符合 [OpenTelemetry 事件上的 `prompt.id` 屬性](/zh-TW/monitoring-usage#event-correlation-attributes)。在第一次使用者輸入之前不存在。{/* min-version: 2.1.196 */}需要 Claude Code v2.1.196 或更新版本 |
| `transcript_path`                                                                | 對話記錄檔案的路徑                                                                                                                                                                                  |
| `version`                                                                        | Claude Code 版本                                                                                                                                                                             |
| `output_style.name`                                                              | 目前輸出樣式的名稱                                                                                                                                                                                  |
| `vim.mode`                                                                       | 啟用 [vim 模式](/zh-TW/interactive-mode#vim-editor-mode)時的目前 vim 模式（`NORMAL`、`INSERT`、`VISUAL` 或 `VISUAL LINE`）                                                                                |
| `agent.name`                                                                     | 使用 `--agent` 旗標或設定的代理設定執行時的代理名稱                                                                                                                                                            |
| `pr.number`, `pr.url`                                                            | 目前分支的開啟提取請求。鏡像底部狀態列中的 PR 徽章。在找到 PR 之前、不在 git 儲存庫中或 PR 合併或關閉後不存在                                                                                                                            |
| `pr.review_state`                                                                | 開啟 PR 的審查狀態：`approved`、`pending`、`changes_requested` 或 `draft`。即使 `pr` 存在，也可能獨立不存在                                                                                                         |
| `worktree.name`                                                                  | 作用中 worktree 的名稱。僅在 `--worktree` 工作階段期間出現                                                                                                                                                  |
| `worktree.path`                                                                  | worktree 目錄的絕對路徑                                                                                                                                                                           |
| `worktree.branch`                                                                | worktree 的 Git 分支名稱（例如 `"worktree-my-feature"`）。對於基於 hook 的 worktree 不存在                                                                                                                   |
| `worktree.original_cwd`                                                          | Claude 進入 worktree 之前所在的目錄                                                                                                                                                                 |
| `worktree.original_branch`                                                       | 進入 worktree 之前簽出的 Git 分支。對於基於 hook 的 worktree 不存在                                                                                                                                          |

<Accordion title="完整 JSON 架構">
  您的狀態列命令透過 stdin 接收此 JSON 結構：

  ```json theme={null}
  {
    "cwd": "/current/working/directory",
    "session_id": "abc123...",
    "session_name": "my-session",
    "prompt_id": "550e8400-e29b-41d4-a716-446655440000",
    "transcript_path": "/path/to/transcript.jsonl",
    "model": {
      "id": "claude-opus-4-8",
      "display_name": "Opus"
    },
    "workspace": {
      "current_dir": "/current/working/directory",
      "project_dir": "/original/project/directory",
      "added_dirs": [],
      "git_worktree": "feature-xyz",
      "repo": {
        "host": "github.com",
        "owner": "anthropics",
        "name": "claude-code"
      }
    },
    "version": "2.1.90",
    "output_style": {
      "name": "default"
    },
    "cost": {
      "total_cost_usd": 0.01234,
      "total_duration_ms": 45000,
      "total_api_duration_ms": 2300,
      "total_lines_added": 156,
      "total_lines_removed": 23
    },
    "context_window": {
      "total_input_tokens": 15500,
      "total_output_tokens": 1200,
      "context_window_size": 200000,
      "used_percentage": 8,
      "remaining_percentage": 92,
      "current_usage": {
        "input_tokens": 8500,
        "output_tokens": 1200,
        "cache_creation_input_tokens": 5000,
        "cache_read_input_tokens": 2000
      }
    },
    "exceeds_200k_tokens": false,
    "effort": {
      "level": "high"
    },
    "thinking": {
      "enabled": true
    },
    "rate_limits": {
      "five_hour": {
        "used_percentage": 23.5,
        "resets_at": 1738425600
      },
      "seven_day": {
        "used_percentage": 41.2,
        "resets_at": 1738857600
      }
    },
    "vim": {
      "mode": "NORMAL"
    },
    "agent": {
      "name": "security-reviewer"
    },
    "pr": {
      "number": 1234,
      "url": "https://github.com/anthropics/claude-code/pull/1234",
      "review_state": "pending"
    },
    "worktree": {
      "name": "my-feature",
      "path": "/path/to/.claude/worktrees/my-feature",
      "branch": "worktree-my-feature",
      "original_cwd": "/path/to/project",
      "original_branch": "main"
    }
  }
  ```

  **可能不存在的欄位**（不在 JSON 中）：

  * `session_name`：僅在使用 `--name` 或 `/rename` 設定自訂名稱時出現
  * `prompt_id`：僅在第一次使用者輸入後出現
  * `workspace.git_worktree`：僅當目前目錄位於連結 git worktree 內時出現
  * `workspace.repo`：僅在 git 儲存庫內且設定了 `origin` 遠端時出現
  * `effort`：僅當目前模型支援推理努力參數時出現
  * `vim`：僅在啟用 vim 模式時出現
  * `agent`：僅在使用 `--agent` 旗標或設定的代理設定執行時出現
  * `pr`：僅在為目前分支找到開啟 PR 時出現，一旦 PR 合併或關閉就會移除。`pr.review_state` 可能獨立不存在
  * `worktree`：僅在 `--worktree` 工作階段期間出現。存在時，`branch` 和 `original_branch` 對於基於 hook 的 worktree 也可能不存在
  * `rate_limits`：僅對 Claude.ai 訂閱者（Pro/Max）在工作階段中第一次 API 回應後出現。每個視窗（`five_hour`、`seven_day`）可能獨立不存在。使用 `jq -r '.rate_limits.five_hour.used_percentage // empty'` 以優雅地處理不存在的情況。

  **可能為 `null` 的欄位**：

  * `context_window.current_usage`：在工作階段中第一次 API 呼叫之前為 `null`，以及在 `/compact` 之後直到下一次 API 呼叫重新填入為止
  * `context_window.used_percentage`, `context_window.remaining_percentage`：在工作階段早期可能為 `null`

  在您的指令碼中使用條件存取處理遺漏的欄位，並使用後備預設值處理 null 值。
</Accordion>

<h3 id="context-window-fields">
  Context window 欄位
</h3>

`context_window` 物件描述來自最近 API 回應的即時 context window。自 v2.1.132 起，`total_input_tokens` 和 `total_output_tokens` 反映目前 context 使用情況，而非累積工作階段總計。

* **合併總計**（`total_input_tokens`, `total_output_tokens`）：目前在 context window 中的令牌。`total_input_tokens` 是 `input_tokens`、`cache_creation_input_tokens` 和 `cache_read_input_tokens` 的總和；`total_output_tokens` 是最近回應中的輸出令牌。在第一次 API 回應之前兩者都是 `0`。
* **按元件使用情況**（`current_usage`）：相同的令牌計數按類別分解。當您需要將快取命中與新輸入分開時，請使用此項。

`current_usage` 物件包含：

* `input_tokens`：目前 context 中的輸入令牌
* `output_tokens`：產生的輸出令牌
* `cache_creation_input_tokens`：寫入快取的令牌
* `cache_read_input_tokens`：從快取讀取的令牌

如需了解快取欄位的含義及其計費方式，請參閱[檢查快取效能](/zh-TW/prompt-caching#check-cache-performance)。

`used_percentage` 欄位僅從輸入令牌計算：`input_tokens + cache_creation_input_tokens + cache_read_input_tokens`。它不包括 `output_tokens`。

如果您從 `current_usage` 手動計算 context 百分比，請使用相同的僅輸入公式以符合 `used_percentage`。

`current_usage` 物件在工作階段中第一次 API 呼叫之前為 `null`，以及在 `/compact` 之後直到下一次 API 呼叫重新填入為止再次為 `null`。

<h2 id="examples">
  範例
</h2>

這些範例展示常見的狀態列模式。若要使用任何範例：

1. 將指令碼儲存到檔案，例如 `~/.claude/statusline.sh`（或 `.py`/`.js`）
2. 使其可執行：`chmod +x ~/.claude/statusline.sh`
3. 將路徑新增到您的[設定](#manually-configure-a-status-line)

Bash 範例使用 [`jq`](https://jqlang.github.io/jq/) 來解析 JSON。Python 和 Node.js 具有內建的 JSON 解析。

<h3 id="context-window-usage">
  Context window 使用情況
</h3>

顯示目前模型和 context window 使用情況，帶有視覺進度列。每個指令碼從 stdin 讀取 JSON，提取 `used_percentage` 欄位，並建立一個 10 字元的列，其中填充的塊（▓）代表使用情況：

<Frame>
  <img src="https://mintcdn.com/claude-code/nibzesLaJVh4ydOq/images/statusline-context-window-usage.png?fit=max&auto=format&n=nibzesLaJVh4ydOq&q=85&s=15b58ab3602f036939145dde3165c6f7" alt="狀態列顯示模型名稱和帶有百分比的進度列" width="448" height="152" data-path="images/statusline-context-window-usage.png" />
</Frame>

<CodeGroup>
  ```bash Bash theme={null}
  #!/bin/bash
  # Read all of stdin into a variable
  input=$(cat)

  # Extract fields with jq, "// 0" provides fallback for null
  MODEL=$(echo "$input" | jq -r '.model.display_name')
  PCT=$(echo "$input" | jq -r '.context_window.used_percentage // 0' | cut -d. -f1)

  # Build progress bar: printf -v creates a run of spaces, then
  # ${var// /▓} replaces each space with a block character
  BAR_WIDTH=10
  FILLED=$((PCT * BAR_WIDTH / 100))
  EMPTY=$((BAR_WIDTH - FILLED))
  BAR=""
  [ "$FILLED" -gt 0 ] && printf -v FILL "%${FILLED}s" && BAR="${FILL// /▓}"
  [ "$EMPTY" -gt 0 ] && printf -v PAD "%${EMPTY}s" && BAR="${BAR}${PAD// /░}"

  echo "[$MODEL] $BAR $PCT%"
  ```

  ```python Python theme={null}
  #!/usr/bin/env python3
  import json, sys

  # json.load reads and parses stdin in one step
  data = json.load(sys.stdin)
  model = data['model']['display_name']
  # "or 0" handles null values
  pct = int(data.get('context_window', {}).get('used_percentage', 0) or 0)

  # String multiplication builds the bar
  filled = pct * 10 // 100
  bar = '▓' * filled + '░' * (10 - filled)

  print(f"[{model}] {bar} {pct}%")
  ```

  ```javascript Node.js theme={null}
  #!/usr/bin/env node
  // Node.js reads stdin asynchronously with events
  let input = '';
  process.stdin.on('data', chunk => input += chunk);
  process.stdin.on('end', () => {
      const data = JSON.parse(input);
      const model = data.model.display_name;
      // Optional chaining (?.) safely handles null fields
      const pct = Math.floor(data.context_window?.used_percentage || 0);

      // String.repeat() builds the bar
      const filled = Math.floor(pct * 10 / 100);
      const bar = '▓'.repeat(filled) + '░'.repeat(10 - filled);

      console.log(`[${model}] ${bar} ${pct}%`);
  });
  ```
</CodeGroup>

<h3 id="git-status-with-colors">
  Git 狀態與顏色
</h3>

顯示 git 分支，帶有暫存和修改檔案的顏色編碼指示器。此指令碼使用 [ANSI 逃逸碼](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors)表示終端顏色：`\033[32m` 是綠色，`\033[33m` 是黃色，`\033[0m` 重設為預設值。

<Frame>
  <img src="https://mintcdn.com/claude-code/nibzesLaJVh4ydOq/images/statusline-git-context.png?fit=max&auto=format&n=nibzesLaJVh4ydOq&q=85&s=e656f34f90d1d9a1d0e220988914345f" alt="狀態列顯示模型、目錄、git 分支和暫存和修改檔案的彩色指示器" width="742" height="178" data-path="images/statusline-git-context.png" />
</Frame>

每個指令碼檢查目前目錄是否是 git 儲存庫，計算暫存和修改檔案，並顯示顏色編碼的指示器：

<CodeGroup>
  ```bash Bash theme={null}
  #!/bin/bash
  input=$(cat)

  MODEL=$(echo "$input" | jq -r '.model.display_name')
  DIR=$(echo "$input" | jq -r '.workspace.current_dir')

  GREEN='\033[32m'
  YELLOW='\033[33m'
  RESET='\033[0m'

  if git rev-parse --git-dir > /dev/null 2>&1; then
      BRANCH=$(git branch --show-current 2>/dev/null)
      STAGED=$(git diff --cached --numstat 2>/dev/null | wc -l | tr -d ' ')
      MODIFIED=$(git diff --numstat 2>/dev/null | wc -l | tr -d ' ')

      GIT_STATUS=""
      [ "$STAGED" -gt 0 ] && GIT_STATUS="${GREEN}+${STAGED}${RESET}"
      [ "$MODIFIED" -gt 0 ] && GIT_STATUS="${GIT_STATUS}${YELLOW}~${MODIFIED}${RESET}"

      echo -e "[$MODEL] 📁 ${DIR##*/} | 🌿 $BRANCH $GIT_STATUS"
  else
      echo "[$MODEL] 📁 ${DIR##*/}"
  fi
  ```

  ```python Python theme={null}
  #!/usr/bin/env python3
  import json, sys, subprocess, os

  data = json.load(sys.stdin)
  model = data['model']['display_name']
  directory = os.path.basename(data['workspace']['current_dir'])

  GREEN, YELLOW, RESET = '\033[32m', '\033[33m', '\033[0m'

  try:
      subprocess.check_output(['git', 'rev-parse', '--git-dir'], stderr=subprocess.DEVNULL)
      branch = subprocess.check_output(['git', 'branch', '--show-current'], text=True).strip()
      staged_output = subprocess.check_output(['git', 'diff', '--cached', '--numstat'], text=True).strip()
      modified_output = subprocess.check_output(['git', 'diff', '--numstat'], text=True).strip()
      staged = len(staged_output.split('\n')) if staged_output else 0
      modified = len(modified_output.split('\n')) if modified_output else 0

      git_status = f"{GREEN}+{staged}{RESET}" if staged else ""
      git_status += f"{YELLOW}~{modified}{RESET}" if modified else ""

      print(f"[{model}] 📁 {directory} | 🌿 {branch} {git_status}")
  except:
      print(f"[{model}] 📁 {directory}")
  ```

  ```javascript Node.js theme={null}
  #!/usr/bin/env node
  const { execSync } = require('child_process');
  const path = require('path');

  let input = '';
  process.stdin.on('data', chunk => input += chunk);
  process.stdin.on('end', () => {
      const data = JSON.parse(input);
      const model = data.model.display_name;
      const dir = path.basename(data.workspace.current_dir);

      const GREEN = '\x1b[32m', YELLOW = '\x1b[33m', RESET = '\x1b[0m';

      try {
          execSync('git rev-parse --git-dir', { stdio: 'ignore' });
          const branch = execSync('git branch --show-current', { encoding: 'utf8' }).trim();
          const staged = execSync('git diff --cached --numstat', { encoding: 'utf8' }).trim().split('\n').filter(Boolean).length;
          const modified = execSync('git diff --numstat', { encoding: 'utf8' }).trim().split('\n').filter(Boolean).length;

          let gitStatus = staged ? `${GREEN}+${staged}${RESET}` : '';
          gitStatus += modified ? `${YELLOW}~${modified}${RESET}` : '';

          console.log(`[${model}] 📁 ${dir} | 🌿 ${branch} ${gitStatus}`);
      } catch {
          console.log(`[${model}] 📁 ${dir}`);
      }
  });
  ```
</CodeGroup>

<h3 id="cost-and-duration-tracking">
  成本和持續時間追蹤
</h3>

追蹤您的工作階段 API 成本和經過的時間。`cost.total_cost_usd` 欄位累積目前工作階段中所有 API 呼叫的估計成本。`cost.total_duration_ms` 欄位測量自工作階段開始以來的總經過時間，而 `cost.total_api_duration_ms` 僅追蹤等待 API 回應所花費的時間。

每個指令碼將成本格式化為貨幣，並將毫秒轉換為分鐘和秒：

<Frame>
  <img src="https://mintcdn.com/claude-code/nibzesLaJVh4ydOq/images/statusline-cost-tracking.png?fit=max&auto=format&n=nibzesLaJVh4ydOq&q=85&s=e3444a51fe6f3440c134bd5f1f08ad29" alt="狀態列顯示模型名稱、工作階段成本和持續時間" width="588" height="180" data-path="images/statusline-cost-tracking.png" />
</Frame>

<CodeGroup>
  ```bash Bash theme={null}
  #!/bin/bash
  input=$(cat)

  MODEL=$(echo "$input" | jq -r '.model.display_name')
  COST=$(echo "$input" | jq -r '.cost.total_cost_usd // 0')
  DURATION_MS=$(echo "$input" | jq -r '.cost.total_duration_ms // 0')

  COST_FMT=$(printf '$%.2f' "$COST")
  DURATION_SEC=$((DURATION_MS / 1000))
  MINS=$((DURATION_SEC / 60))
  SECS=$((DURATION_SEC % 60))

  echo "[$MODEL] 💰 $COST_FMT | ⏱️ ${MINS}m ${SECS}s"
  ```

  ```python Python theme={null}
  #!/usr/bin/env python3
  import json, sys

  data = json.load(sys.stdin)
  model = data['model']['display_name']
  cost = data.get('cost', {}).get('total_cost_usd', 0) or 0
  duration_ms = data.get('cost', {}).get('total_duration_ms', 0) or 0

  duration_sec = duration_ms // 1000
  mins, secs = duration_sec // 60, duration_sec % 60

  print(f"[{model}] 💰 ${cost:.2f} | ⏱️ {mins}m {secs}s")
  ```

  ```javascript Node.js theme={null}
  #!/usr/bin/env node
  let input = '';
  process.stdin.on('data', chunk => input += chunk);
  process.stdin.on('end', () => {
      const data = JSON.parse(input);
      const model = data.model.display_name;
      const cost = data.cost?.total_cost_usd || 0;
      const durationMs = data.cost?.total_duration_ms || 0;

      const durationSec = Math.floor(durationMs / 1000);
      const mins = Math.floor(durationSec / 60);
      const secs = durationSec % 60;

      console.log(`[${model}] 💰 $${cost.toFixed(2)} | ⏱️ ${mins}m ${secs}s`);
  });
  ```
</CodeGroup>

<h3 id="display-multiple-lines">
  顯示多行
</h3>

您的指令碼可以輸出多行以建立更豐富的顯示。每個 `echo` 陳述式在狀態區域中產生單獨的行。

<Frame>
  <img src="https://mintcdn.com/claude-code/nibzesLaJVh4ydOq/images/statusline-multiline.png?fit=max&auto=format&n=nibzesLaJVh4ydOq&q=85&s=60f11387658acc9ff75158ae85f2ac87" alt="多行狀態列，在第一行顯示模型名稱、目錄、git 分支，在第二行顯示 context 使用進度列、成本和持續時間" width="776" height="212" data-path="images/statusline-multiline.png" />
</Frame>

此範例結合了多種技術：基於閾值的顏色（70% 以下為綠色，70-89% 為黃色，90%+ 為紅色）、進度列和 git 分支資訊。每個 `print` 或 `echo` 陳述式建立單獨的行：

<CodeGroup>
  ```bash Bash theme={null}
  #!/bin/bash
  input=$(cat)

  MODEL=$(echo "$input" | jq -r '.model.display_name')
  DIR=$(echo "$input" | jq -r '.workspace.current_dir')
  COST=$(echo "$input" | jq -r '.cost.total_cost_usd // 0')
  PCT=$(echo "$input" | jq -r '.context_window.used_percentage // 0' | cut -d. -f1)
  DURATION_MS=$(echo "$input" | jq -r '.cost.total_duration_ms // 0')

  CYAN='\033[36m'; GREEN='\033[32m'; YELLOW='\033[33m'; RED='\033[31m'; RESET='\033[0m'

  # Pick bar color based on context usage
  if [ "$PCT" -ge 90 ]; then BAR_COLOR="$RED"
  elif [ "$PCT" -ge 70 ]; then BAR_COLOR="$YELLOW"
  else BAR_COLOR="$GREEN"; fi

  FILLED=$((PCT / 10)); EMPTY=$((10 - FILLED))
  printf -v FILL "%${FILLED}s"; printf -v PAD "%${EMPTY}s"
  BAR="${FILL// /█}${PAD// /░}"

  MINS=$((DURATION_MS / 60000)); SECS=$(((DURATION_MS % 60000) / 1000))

  BRANCH=""
  git rev-parse --git-dir > /dev/null 2>&1 && BRANCH=" | 🌿 $(git branch --show-current 2>/dev/null)"

  echo -e "${CYAN}[$MODEL]${RESET} 📁 ${DIR##*/}$BRANCH"
  COST_FMT=$(printf '$%.2f' "$COST")
  echo -e "${BAR_COLOR}${BAR}${RESET} ${PCT}% | ${YELLOW}${COST_FMT}${RESET} | ⏱️ ${MINS}m ${SECS}s"
  ```

  ```python Python theme={null}
  #!/usr/bin/env python3
  import json, sys, subprocess, os

  data = json.load(sys.stdin)
  model = data['model']['display_name']
  directory = os.path.basename(data['workspace']['current_dir'])
  cost = data.get('cost', {}).get('total_cost_usd', 0) or 0
  pct = int(data.get('context_window', {}).get('used_percentage', 0) or 0)
  duration_ms = data.get('cost', {}).get('total_duration_ms', 0) or 0

  CYAN, GREEN, YELLOW, RED, RESET = '\033[36m', '\033[32m', '\033[33m', '\033[31m', '\033[0m'

  bar_color = RED if pct >= 90 else YELLOW if pct >= 70 else GREEN
  filled = pct // 10
  bar = '█' * filled + '░' * (10 - filled)

  mins, secs = duration_ms // 60000, (duration_ms % 60000) // 1000

  try:
      branch = subprocess.check_output(['git', 'branch', '--show-current'], text=True, stderr=subprocess.DEVNULL).strip()
      branch = f" | 🌿 {branch}" if branch else ""
  except:
      branch = ""

  print(f"{CYAN}[{model}]{RESET} 📁 {directory}{branch}")
  print(f"{bar_color}{bar}{RESET} {pct}% | {YELLOW}${cost:.2f}{RESET} | ⏱️ {mins}m {secs}s")
  ```

  ```javascript Node.js theme={null}
  #!/usr/bin/env node
  const { execSync } = require('child_process');
  const path = require('path');

  let input = '';
  process.stdin.on('data', chunk => input += chunk);
  process.stdin.on('end', () => {
      const data = JSON.parse(input);
      const model = data.model.display_name;
      const dir = path.basename(data.workspace.current_dir);
      const cost = data.cost?.total_cost_usd || 0;
      const pct = Math.floor(data.context_window?.used_percentage || 0);
      const durationMs = data.cost?.total_duration_ms || 0;

      const CYAN = '\x1b[36m', GREEN = '\x1b[32m', YELLOW = '\x1b[33m', RED = '\x1b[31m', RESET = '\x1b[0m';

      const barColor = pct >= 90 ? RED : pct >= 70 ? YELLOW : GREEN;
      const filled = Math.floor(pct / 10);
      const bar = '█'.repeat(filled) + '░'.repeat(10 - filled);

      const mins = Math.floor(durationMs / 60000);
      const secs = Math.floor((durationMs % 60000) / 1000);

      let branch = '';
      try {
          branch = execSync('git branch --show-current', { encoding: 'utf8', stdio: ['pipe', 'pipe', 'ignore'] }).trim();
          branch = branch ? ` | 🌿 ${branch}` : '';
      } catch {}

      console.log(`${CYAN}[${model}]${RESET} 📁 ${dir}${branch}`);
      console.log(`${barColor}${bar}${RESET} ${pct}% | ${YELLOW}$${cost.toFixed(2)}${RESET} | ⏱️ ${mins}m ${secs}s`);
  });
  ```
</CodeGroup>

<h3 id="clickable-links">
  可點擊的連結
</h3>

此範例建立指向您的 GitHub 儲存庫的可點擊連結。它讀取 git 遠端 URL，使用 `sed` 將 SSH 格式轉換為 HTTPS，並將儲存庫名稱包裝在 OSC 8 逃逸碼中。按住 Cmd（macOS）或 Ctrl（Windows/Linux）並點擊以在瀏覽器中開啟連結。

<Frame>
  <img src="https://mintcdn.com/claude-code/nibzesLaJVh4ydOq/images/statusline-links.png?fit=max&auto=format&n=nibzesLaJVh4ydOq&q=85&s=4bcc6e7deb7cf52f41ab85a219b52661" alt="狀態列顯示指向 GitHub 儲存庫的可點擊連結" width="726" height="198" data-path="images/statusline-links.png" />
</Frame>

每個指令碼取得 git 遠端 URL，將 SSH 格式轉換為 HTTPS，並將儲存庫名稱包裝在 OSC 8 逃逸碼中。Bash 版本使用 `printf '%b'`，它比 `echo -e` 更可靠地跨不同 shell 解釋反斜杠逃逸：

<CodeGroup>
  ```bash Bash theme={null}
  #!/bin/bash
  input=$(cat)

  MODEL=$(echo "$input" | jq -r '.model.display_name')

  # Convert git SSH URL to HTTPS
  REMOTE=$(git remote get-url origin 2>/dev/null | sed 's/git@github.com:/https:\/\/github.com\//' | sed 's/\.git$//')

  if [ -n "$REMOTE" ]; then
      REPO_NAME=$(basename "$REMOTE")
      # OSC 8 format: \e]8;;URL\a then TEXT then \e]8;;\a
      # printf %b interprets escape sequences reliably across shells
      printf '%b' "[$MODEL] 🔗 \e]8;;${REMOTE}\a${REPO_NAME}\e]8;;\a\n"
  else
      echo "[$MODEL]"
  fi
  ```

  ```python Python theme={null}
  #!/usr/bin/env python3
  import json, sys, subprocess, re, os

  data = json.load(sys.stdin)
  model = data['model']['display_name']

  # Get git remote URL
  try:
      remote = subprocess.check_output(
          ['git', 'remote', 'get-url', 'origin'],
          stderr=subprocess.DEVNULL, text=True
      ).strip()
      # Convert SSH to HTTPS format
      remote = re.sub(r'^git@github\.com:', 'https://github.com/', remote)
      remote = re.sub(r'\.git$', '', remote)
      repo_name = os.path.basename(remote)
      # OSC 8 escape sequences
      link = f"\033]8;;{remote}\a{repo_name}\033]8;;\a"
      print(f"[{model}] 🔗 {link}")
  except:
      print(f"[{model}]")
  ```

  ```javascript Node.js theme={null}
  #!/usr/bin/env node
  const { execSync } = require('child_process');
  const path = require('path');

  let input = '';
  process.stdin.on('data', chunk => input += chunk);
  process.stdin.on('end', () => {
      const data = JSON.parse(input);
      const model = data.model.display_name;

      try {
          let remote = execSync('git remote get-url origin', { encoding: 'utf8', stdio: ['pipe', 'pipe', 'ignore'] }).trim();
          // Convert SSH to HTTPS format
          remote = remote.replace(/^git@github\.com:/, 'https://github.com/').replace(/\.git$/, '');
          const repoName = path.basename(remote);
          // OSC 8 escape sequences
          const link = `\x1b]8;;${remote}\x07${repoName}\x1b]8;;\x07`;
          console.log(`[${model}] 🔗 ${link}`);
      } catch {
          console.log(`[${model}]`);
      }
  });
  ```
</CodeGroup>

<h3 id="rate-limit-usage">
  速率限制使用情況
</h3>

在狀態列中顯示 Claude.ai 訂閱速率限制使用情況。`rate_limits` 物件包含 `five_hour`（5 小時滾動視窗）和 `seven_day`（每週）視窗。每個視窗提供 `used_percentage`（0-100）和 `resets_at`（Unix 紀元秒，視窗重設時）。

此欄位僅對 Claude.ai 訂閱者（Pro/Max）在第一次 API 回應後出現。每個指令碼優雅地處理不存在的欄位：

<CodeGroup>
  ```bash Bash theme={null}
  #!/bin/bash
  input=$(cat)

  MODEL=$(echo "$input" | jq -r '.model.display_name')
  # "// empty" produces no output when rate_limits is absent
  FIVE_H=$(echo "$input" | jq -r '.rate_limits.five_hour.used_percentage // empty')
  WEEK=$(echo "$input" | jq -r '.rate_limits.seven_day.used_percentage // empty')

  LIMITS=""
  [ -n "$FIVE_H" ] && LIMITS="5h: $(printf '%.0f' "$FIVE_H")%"
  [ -n "$WEEK" ] && LIMITS="${LIMITS:+$LIMITS }7d: $(printf '%.0f' "$WEEK")%"

  [ -n "$LIMITS" ] && echo "[$MODEL] | $LIMITS" || echo "[$MODEL]"
  ```

  ```python Python theme={null}
  #!/usr/bin/env python3
  import json, sys

  data = json.load(sys.stdin)
  model = data['model']['display_name']

  parts = []
  rate = data.get('rate_limits', {})
  five_h = rate.get('five_hour', {}).get('used_percentage')
  week = rate.get('seven_day', {}).get('used_percentage')

  if five_h is not None:
      parts.append(f"5h: {five_h:.0f}%")
  if week is not None:
      parts.append(f"7d: {week:.0f}%")

  if parts:
      print(f"[{model}] | {' '.join(parts)}")
  else:
      print(f"[{model}]")
  ```

  ```javascript Node.js theme={null}
  #!/usr/bin/env node
  let input = '';
  process.stdin.on('data', chunk => input += chunk);
  process.stdin.on('end', () => {
      const data = JSON.parse(input);
      const model = data.model.display_name;

      const parts = [];
      const fiveH = data.rate_limits?.five_hour?.used_percentage;
      const week = data.rate_limits?.seven_day?.used_percentage;

      if (fiveH != null) parts.push(`5h: ${Math.round(fiveH)}%`);
      if (week != null) parts.push(`7d: ${Math.round(week)}%`);

      console.log(parts.length ? `[${model}] | ${parts.join(' ')}` : `[${model}]`);
  });
  ```
</CodeGroup>

<h3 id="cache-expensive-operations">
  快取昂貴的操作
</h3>

您的狀態列指令碼在活躍工作階段期間頻繁執行。`git status` 或 `git diff` 等命令可能很慢，特別是在大型儲存庫中。此範例將 git 資訊快取到臨時檔案，並且僅每 5 秒重新整理一次。

快取檔案名稱需要在工作階段內的狀態列呼叫中保持穩定，但在工作階段之間保持唯一，以便不同儲存庫中的並行工作階段不會讀取彼此的快取 git 狀態。基於程序的識別碼（如 `$$`、`os.getpid()` 或 `process.pid`）在每次呼叫時都會變更，並會破壞快取。改用 JSON 輸入中的 `session_id`：它在工作階段的生命週期內保持穩定，並且每個工作階段都是唯一的。

每個指令碼在執行 git 命令之前檢查快取檔案是否遺漏或超過 5 秒：

<CodeGroup>
  ```bash Bash theme={null}
  #!/bin/bash
  input=$(cat)

  MODEL=$(echo "$input" | jq -r '.model.display_name')
  DIR=$(echo "$input" | jq -r '.workspace.current_dir')
  SESSION_ID=$(echo "$input" | jq -r '.session_id')

  CACHE_FILE="/tmp/statusline-git-cache-$SESSION_ID"
  CACHE_MAX_AGE=5  # seconds

  cache_is_stale() {
      [ ! -f "$CACHE_FILE" ] || \
      # stat -f %m is macOS, stat -c %Y is Linux
      [ $(($(date +%s) - $(stat -f %m "$CACHE_FILE" 2>/dev/null || stat -c %Y "$CACHE_FILE" 2>/dev/null || echo 0))) -gt $CACHE_MAX_AGE ]
  }

  if cache_is_stale; then
      if git rev-parse --git-dir > /dev/null 2>&1; then
          BRANCH=$(git branch --show-current 2>/dev/null)
          STAGED=$(git diff --cached --numstat 2>/dev/null | wc -l | tr -d ' ')
          MODIFIED=$(git diff --numstat 2>/dev/null | wc -l | tr -d ' ')
          echo "$BRANCH|$STAGED|$MODIFIED" > "$CACHE_FILE"
      else
          echo "||" > "$CACHE_FILE"
      fi
  fi

  IFS='|' read -r BRANCH STAGED MODIFIED < "$CACHE_FILE"

  if [ -n "$BRANCH" ]; then
      echo "[$MODEL] 📁 ${DIR##*/} | 🌿 $BRANCH +$STAGED ~$MODIFIED"
  else
      echo "[$MODEL] 📁 ${DIR##*/}"
  fi
  ```

  ```python Python theme={null}
  #!/usr/bin/env python3
  import json, sys, subprocess, os, time

  data = json.load(sys.stdin)
  model = data['model']['display_name']
  directory = os.path.basename(data['workspace']['current_dir'])
  session_id = data['session_id']

  CACHE_FILE = f"/tmp/statusline-git-cache-{session_id}"
  CACHE_MAX_AGE = 5  # seconds

  def cache_is_stale():
      if not os.path.exists(CACHE_FILE):
          return True
      return time.time() - os.path.getmtime(CACHE_FILE) > CACHE_MAX_AGE

  if cache_is_stale():
      try:
          subprocess.check_output(['git', 'rev-parse', '--git-dir'], stderr=subprocess.DEVNULL)
          branch = subprocess.check_output(['git', 'branch', '--show-current'], text=True).strip()
          staged = subprocess.check_output(['git', 'diff', '--cached', '--numstat'], text=True).strip()
          modified = subprocess.check_output(['git', 'diff', '--numstat'], text=True).strip()
          staged_count = len(staged.split('\n')) if staged else 0
          modified_count = len(modified.split('\n')) if modified else 0
          with open(CACHE_FILE, 'w') as f:
              f.write(f"{branch}|{staged_count}|{modified_count}")
      except:
          with open(CACHE_FILE, 'w') as f:
              f.write("||")

  with open(CACHE_FILE) as f:
      branch, staged, modified = f.read().strip().split('|')

  if branch:
      print(f"[{model}] 📁 {directory} | 🌿 {branch} +{staged} ~{modified}")
  else:
      print(f"[{model}] 📁 {directory}")
  ```

  ```javascript Node.js theme={null}
  #!/usr/bin/env node
  const { execSync } = require('child_process');
  const fs = require('fs');
  const path = require('path');

  let input = '';
  process.stdin.on('data', chunk => input += chunk);
  process.stdin.on('end', () => {
      const data = JSON.parse(input);
      const model = data.model.display_name;
      const dir = path.basename(data.workspace.current_dir);
      const sessionId = data.session_id;

      const CACHE_FILE = `/tmp/statusline-git-cache-${sessionId}`;
      const CACHE_MAX_AGE = 5; // seconds

      const cacheIsStale = () => {
          if (!fs.existsSync(CACHE_FILE)) return true;
          return (Date.now() / 1000) - fs.statSync(CACHE_FILE).mtimeMs / 1000 > CACHE_MAX_AGE;
      };

      if (cacheIsStale()) {
          try {
              execSync('git rev-parse --git-dir', { stdio: 'ignore' });
              const branch = execSync('git branch --show-current', { encoding: 'utf8' }).trim();
              const staged = execSync('git diff --cached --numstat', { encoding: 'utf8' }).trim().split('\n').filter(Boolean).length;
              const modified = execSync('git diff --numstat', { encoding: 'utf8' }).trim().split('\n').filter(Boolean).length;
              fs.writeFileSync(CACHE_FILE, `${branch}|${staged}|${modified}`);
          } catch {
              fs.writeFileSync(CACHE_FILE, '||');
          }
      }

      const [branch, staged, modified] = fs.readFileSync(CACHE_FILE, 'utf8').trim().split('|');

      if (branch) {
          console.log(`[${model}] 📁 ${dir} | 🌿 ${branch} +${staged} ~${modified}`);
      } else {
          console.log(`[${model}] 📁 ${dir}`);
      }
  });
  ```
</CodeGroup>

<h3 id="windows-configuration">
  Windows 設定
</h3>

在 Windows 上，Claude Code 透過 Git Bash 執行狀態列命令（如果已安裝 Git Bash），或在 Git Bash 不存在時透過 PowerShell 執行。若要執行 PowerShell 指令碼作為您的狀態列，請透過 `powershell` 呼叫它。這在任一 shell 中都有效：

<CodeGroup>
  ```json settings.json theme={null}
  {
    "statusLine": {
      "type": "command",
      "command": "powershell -NoProfile -File C:/Users/username/.claude/statusline.ps1"
    }
  }
  ```

  ```powershell statusline.ps1 theme={null}
  $input_json = $input | Out-String | ConvertFrom-Json
  $cwd = $input_json.cwd
  $model = $input_json.model.display_name
  $used = $input_json.context_window.used_percentage
  $dirname = Split-Path $cwd -Leaf

  if ($used) {
      Write-Host "$dirname [$model] ctx: $used%"
  } else {
      Write-Host "$dirname [$model]"
  }
  ```
</CodeGroup>

或者，當已安裝 Git Bash 時，直接執行 Bash 指令碼：

<CodeGroup>
  ```json settings.json theme={null}
  {
    "statusLine": {
      "type": "command",
      "command": "~/.claude/statusline.sh"
    }
  }
  ```

  ```bash statusline.sh theme={null}
  #!/usr/bin/env bash
  input=$(cat)
  cwd=$(echo "$input" | grep -o '"cwd":"[^"]*"' | cut -d'"' -f4)
  model=$(echo "$input" | grep -o '"display_name":"[^"]*"' | cut -d'"' -f4)
  dirname="${cwd##*[/\\]}"
  echo "$dirname [$model]"
  ```
</CodeGroup>

<h2 id="subagent-status-lines">
  子代理狀態列
</h2>

`subagentStatusLine` 設定為[子代理](/zh-TW/sub-agents)面板中顯示的每個子代理呈現自訂行主體。使用它來用您自己的格式化取代預設的 `name · description · token count` 行。

```json theme={null}
{
  "subagentStatusLine": {
    "type": "command",
    "command": "~/.claude/subagent-statusline.sh"
  }
}
```

命令在每個重新整理刻度上執行一次，所有可見的子代理行作為單個 JSON 物件在 stdin 上傳遞。輸入包括[基本 hook 欄位](/zh-TW/hooks#common-input-fields)加上 `columns`（可用行寬度）和 `tasks` 陣列，其中每個任務具有 `id`、`name`、`type`、`status`、`description`、`label`、`startTime`、`tokenCount`、`tokenSamples` 和 `cwd`。

將一個 JSON 行寫入 stdout，每行您想要覆蓋，形式為 `{"id": "<task id>", "content": "<row body>"}` 。`content` 字串按原樣呈現，包括 ANSI 顏色和 OSC 8 超連結。省略任務的 `id` 以保持該行的預設呈現；發出空 `content` 字串以隱藏它。

適用於 `statusLine` 的相同信任和 `disableAllHooks` 閘門也適用於此。外掛程式可以在其 [`settings.json`](/zh-TW/plugins-reference#standard-plugin-layout) 中提供預設 `subagentStatusLine`。

<h2 id="tips">
  提示
</h2>

* **使用模擬輸入測試**：`echo '{"model":{"display_name":"Opus"},"workspace":{"current_dir":"/home/user/project"},"context_window":{"used_percentage":25},"session_id":"test-session-abc"}' | ./statusline.sh`
* **保持輸出簡短**：狀態列寬度有限，因此長輸出可能會被截斷或換行不當
* **快取慢速操作**：您的指令碼在活躍工作階段期間頻繁執行，因此 `git status` 等命令可能會導致延遲。請參閱[快取範例](#cache-expensive-operations)以瞭解如何處理此問題。

社群專案如 [ccstatusline](https://github.com/sirmalloc/ccstatusline) 和 [starship-claude](https://github.com/martinemde/starship-claude) 提供具有主題和其他功能的預先建立設定。

<h2 id="troubleshooting">
  疑難排解
</h2>

**狀態列未出現**

* 驗證您的指令碼是否可執行：`chmod +x ~/.claude/statusline.sh`
* 檢查您的指令碼是否輸出到 stdout 而不是 stderr
* 手動執行您的指令碼以驗證它產生輸出
* 在安裝了 Git Bash 的 Windows 上，`command` 路徑中的反斜線可能在指令碼執行前被當作逃逸字元消耗。在路徑中使用正斜線。請參閱 [Windows 設定](#windows-configuration)。
* 如果 `disableAllHooks` 在您的設定中設定為 `true`，狀態列也會被停用。移除此設定或將其設定為 `false` 以重新啟用。
* 執行 `claude --debug` 以記錄工作階段中第一次狀態列呼叫的結束代碼和 stderr
* 要求 Claude 讀取您的設定檔案並直接執行 `statusLine` 命令以顯示錯誤

**狀態列顯示 `--` 或空值**

* 欄位在第一次 API 回應完成之前可能為 `null`
* 在您的指令碼中使用後備（例如 jq 中的 `// 0`）處理 null 值
* 如果多個訊息後值仍為空，請重新啟動 Claude Code

**Context 百分比顯示意外值**

* 使用 `used_percentage` 以取得最簡單的準確 context 狀態
* Context 百分比可能與 `/context` 輸出不同，因為每個計算時間不同

**OSC 8 連結不可點擊**

* 驗證您的終端支援 OSC 8 超連結（iTerm2、Kitty、WezTerm）

* Terminal.app 不支援可點擊連結

* 如果連結文字出現但不可點擊，Claude Code 可能未在您的終端中偵測到超連結支援。這通常會影響 Windows Terminal 和其他不在自動偵測清單中的模擬器。設定 `FORCE_HYPERLINK` 環境變數以在啟動 Claude Code 之前覆蓋偵測：

  ```bash theme={null}
  FORCE_HYPERLINK=1 claude
  ```

  在 PowerShell 中，先在目前工作階段中設定變數：

  ```powershell theme={null}
  $env:FORCE_HYPERLINK = "1"; claude
  ```

* SSH 和 tmux 工作階段可能根據設定去除 OSC 序列

* 如果逃逸序列顯示為文字（如 `\e]8;;`），請使用 `printf '%b'` 而不是 `echo -e` 以獲得更可靠的逃逸處理

**逃逸序列的顯示故障**

* 複雜的逃逸序列（ANSI 顏色、OSC 8 連結）如果與其他 UI 更新重疊，偶爾會導致輸出損壞
* 如果您看到損壞的文字，請嘗試簡化您的指令碼為純文字輸出
* 帶有逃逸碼的多行狀態列比單行純文字更容易出現呈現問題

**工作區信任必需**

* 狀態列命令僅在您已接受目前目錄的工作區信任對話時執行。因為 `statusLine` 執行 shell 命令，它需要與 hooks 和其他執行 shell 的設定相同的信任接受。
* 如果未接受信任，您將看到通知 `statusline skipped · restart to fix` 而不是您的狀態列輸出。重新啟動 Claude Code 並接受信任提示以啟用它。

**指令碼錯誤或掛起**

* 以非零代碼結束或不產生輸出的指令碼會導致狀態列變為空白
* 慢速指令碼會阻止狀態列更新，直到它們完成。保持指令碼快速以避免過時的輸出。
* 如果在慢速指令碼執行時觸發新的更新，進行中的指令碼會被取消
* 在設定之前使用模擬輸入獨立測試您的指令碼

**通知共享狀態列行**

* 系統通知（如 MCP 伺服器錯誤和自動更新）顯示在與您的狀態列相同行的右側。暫時性通知（例如 context-low 警告）也會在此區域循環。
* 啟用詳細模式會在此區域新增令牌計數器
* 在狹窄的終端上，這些通知可能會截斷您的狀態列輸出
