understatus 0.7.1

A calm, unobtrusive macOS statusline addon for AI coding CLIs (Claude Code): CPU/memory/disk/network + session info with a quiet glyph theme.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
# understatus

A calm, unobtrusive statusline addon for Claude Code — live CPU, memory, battery, disk, network, and AI session info in a permanent bottom bar that stays out of your way.

![understatus](docs/understatus-calm-preview.png)

---

## Why

Most statusline widgets are noisy. understatus is designed around one principle: **permanent visibility without distraction**.

- **Calm glyph theme** — load stages render as `○ ▁ ▄ ▆ ◆`. Color touches the glyph only; numeric values stay uncolored. Labels and separators are dimmed. At ≥90% CPU the critical glyph `◆` breathes slowly in restrained terracotta (`#b87848` ↔ `#7a5030`) — not red, not flashing.
- **Reactive CPU** — every render takes two snapshots ~25 ms apart and computes true instantaneous CPU% across all cores. No stale load-average guessing.
- **Non-destructive chaining** — `understatus install` detects your existing `statusLine.command`, preserves it in config, and chains it. `uninstall` restores byte-for-byte. Your current setup is never lost.

> **macOS only.** Apple Silicon (arm64) + Intel (x86\_64). Linux is not supported.
>
> **No Xcode required for the prebuilt paths.** Homebrew and npm install **prebuilt binaries** (deployment target macOS 11.0), so they need **no Xcode Command Line Tools and no Rust toolchain**, and run on **macOS 11 (Big Sur) and newer**. Only `cargo install` / building from source compiles locally and therefore needs the Rust toolchain + Command Line Tools.

---

## Install

### Homebrew (recommended)

```bash
brew install ictechgy/understatus/understatus
```

Installs a prebuilt binary — **no Xcode Command Line Tools, no Rust, no compilation.**

> The formula lives in the tap `ictechgy/understatus` (repo: `ictechgy/homebrew-understatus`).

### npm

```bash
npm install -g understatus
```

The npm package downloads the prebuilt macOS binary for your architecture (arm64 / x64) and verifies its SHA-256. **No Xcode / Rust required.** macOS only.

### Cargo

```bash
cargo install understatus
```

Requires Rust 1.75+ **and** the Xcode Command Line Tools (this path compiles from source). If you want to avoid installing the toolchain, use Homebrew or npm above.

### From source

```bash
git clone https://github.com/ictechgy/understatus.git
cd understatus
cargo build --release
# binary at ./target/release/understatus
```

---

## Setup

### Install into Claude Code

```bash
understatus install [--interval N] [--theme NAME] [--yes]
```

This patches `~/.claude/settings.json` non-destructively:

1. Reads your current `statusLine.command` (if any).
2. Saves it as `chain_command` in `~/.config/understatus/config.toml`.
3. Replaces `statusLine.command` with the understatus binary path.
4. Injects `"refreshInterval": N` into `settings.json` and mirrors the same value to `config.toml [refresh].interval_seconds`.

**Flags:**

| Flag | Description |
|------|-------------|
| `--interval N` | Set refresh interval in seconds (integer ≥ 1). |
| `--theme NAME` | Set the theme (see [Themes](#themes) for valid names). |
| `--yes` / `-y` | Skip interactive prompts even in a TTY; use flags / inherited / default values. |

**Interactive prompts (TTY only, without `--yes`):** If a flag is omitted and stdin is a TTY, install asks for each missing value (up to 3 retries per item). Empty input accepts the inherited or default value.

**Interval inheritance on reinstall:** When `--interval` is not supplied, the existing `[refresh].interval_seconds` from `config.toml` is reused. Priority: `--interval` flag > existing config value > default (5 s). This prevents the interval from silently resetting to 5 when you reinstall to change only the theme.

### Uninstall

```bash
understatus uninstall
```

Restores `statusLine.command` and `refreshInterval` to their exact pre-install state. If `refreshInterval` was absent before install, the key is deleted.

---

### ⚠️ Global side-effect: `refreshInterval`

`understatus install` writes `"refreshInterval": N` into `settings.json` (default N = 5). This value applies to the **entire** statusLine subsystem — not just understatus:

- understatus itself spawns as a new process every N seconds.
- Any **chained command** (e.g. `lterm-omc-hud.mjs`) is also re-executed every N seconds.

To decouple heavy chain children, understatus caches their stdout via `chain_cache_ttl_seconds` (default 10 s). The chained child re-spawns at most once per TTL — not every N seconds.

**To save battery on laptops**, raise the interval:

```toml
# ~/.config/understatus/config.toml
[refresh]
interval_seconds = 10   # default: 5
```

Note: increasing `interval_seconds` proportionally slows the terracotta breath animation. Adjust `pulse_period_seconds` accordingly to keep it smooth (`pulse_period / interval >= 6`). If `pulse_period / interval < 6` at install time, understatus prints a warning to stderr.

`understatus uninstall` reverts `refreshInterval` precisely — no residue left behind.

---

## Themes

understatus ships nine built-in themes. Set the active theme in one line:

```toml
# ~/.config/understatus/config.toml
theme = "vivid"
```

Or switch after install without reinstalling:

```bash
understatus theme vivid        # switch to vivid; takes effect on next render
understatus theme              # show current theme and usage hint
understatus themes             # list all available themes
```

### Theme table

| Name | Glyph ramp (idle → crit) | Description |
|------|--------------------------|-------------|
| `calm` | `○ ▁ ▄ ▆ ◆` | Cool blue-grey ladder + terracotta breath at critical. **Default.** |
| `mono` | `○ ▁ ▄ ▆ ◆` | Greyscale only — zero hue across all bands. |
| `vivid` | `░ ▒ ▓ █ █` | Traffic-light colors (green → amber → red) with block-fill glyphs. |
| `ember` | `· ∙ • ● ◉` | Warm amber/terracotta monochromatic ladder with dot glyphs. |
| `emoji` | `😌 🙂 😅 🥵 🔥` | Emoji face ramp. Each glyph occupies 2 terminal columns. |
| `neon` | `░ ▒ ▓ █ █` | Neon cyberpunk — electric cyan → magenta with hue-cycling pulse. |
| `aurora` | `▁ ▃ ▅ ▆ █` | Aurora borealis — teal → purple gradient with flash pulse. |
| `sunset` | `· ∙ • ● ◉` | Sunset — gold → coral → purple with flash pulse. |
| `spectrum` | `▁ ▂ ▄ ▆ █` | Per-band rainbow — green → magenta with hue-cycling pulse. |

**COLOR-ONCE principle:** Color is applied to the glyph character only. Numeric values (CPU%, memory, cost, etc.) are always uncolored regardless of theme.

**Critical breath (≥90% CPU):** The critical-band glyph breathes between `pulse_palette[0]` (bright) and `pulse_palette[1]` (dim) over `pulse_period_seconds`. Hue never shifts — only brightness. The animation requires at least 6 render frames per period (`pulse_period / interval_seconds >= 6`); if this is not satisfied, install prints a warning.

**Per-key override:** `theme` fills only the keys not explicitly set in your config. Any of the eight theme-owned keys (`load_glyphs`, `band_tints`, `pulse_palette`, `label_color`, `separator`, `separator_color`, `hud_seam`, `pulse_style`) written in your config take precedence over the preset.

---

## Pulse styles

When the pulse is active (CPU ≥ `pulse_on_threshold`), `pulse_style` controls how the critical-band glyph animates. There are four styles:

| Style | Behavior |
|-------|----------|
| `calm` | Fixed glyph shape. Terracotta luminance breathing — hue never shifts, only brightness cycles between `pulse_palette[0]` (bright) and `pulse_palette[1]` (dim). Most subtle. **Default for original themes.** |
| `flash` | Fixed glyph shape. Uses the theme's own `pulse_palette` endpoints (the same high/low colors as that theme's `calm` breath), but applies a sharper sine curve — the midpoint brightness contrast is more pronounced (punchier breathing). |
| `hue` | Fixed glyph shape. The glyph tint cycles through the full hue wheel (rainbow shimmer) over one `pulse_period_seconds`. Saturation and value stay constant; only hue rotates 360°. |
| `swap` | Hue cycling (same as `hue`) **plus** glyph shape alternation: the critical glyph swaps between its filled and hollow forms (e.g. `◆` ↔ `◇`) on the second half of each period. Most eye-catching. |

**Flashy theme defaults:** The four bold themes ship with a fitting default style — `neon` and `spectrum` use `hue`; `aurora` and `sunset` use `flash`. The original five themes (`calm`, `mono`, `vivid`, `ember`, `emoji`) all use `calm`. All are overridable per the per-key override rule above.

**When pulse is OFF:** Regardless of `pulse_style`, when CPU is below `pulse_off_threshold` the pulse is inactive and the glyph renders with its static `band_tints` color — no animation of any kind.

### Trigger thresholds

```toml
# ~/.config/understatus/config.toml
[pulse]
pulse_on_threshold  = 90   # default: CPU% at which pulse activates
pulse_off_threshold = 80   # default: CPU% below which pulse deactivates (hysteresis)
```

The pulse turns ON when CPU reaches `pulse_on_threshold` (90) and stays ON until CPU drops below `pulse_off_threshold` (80) — so it keeps animating briefly during cool-down. This avoids flicker at the boundary.

Lower the thresholds to pulse at a lower CPU load:

```toml
[pulse]
pulse_on_threshold  = 75
pulse_off_threshold = 65
```

### Changing the pulse style

```toml
# ~/.config/understatus/config.toml
[pulse]
pulse_style = "hue"   # calm | flash | hue | swap
```

Or switch from the command line (takes effect on the next render):

```bash
understatus pulse hue    # change pulse style
understatus pulse        # print current style
```

---

## Configuration

File: `~/.config/understatus/config.toml`  
All keys are optional; omitting a key uses its default.

| Key | Default | Description |
|-----|---------|-------------|
| `theme` | `"calm"` | Active theme preset. Valid values: `calm`, `mono`, `vivid`, `ember`, `emoji`, `neon`, `aurora`, `sunset`, `spectrum`. The theme fills all eight visual keys not explicitly set in config; individual keys can still override it. |
| `[cpu] sample_window_ms` | `25` | Interval (ms) between the two CPU snapshots. Larger = less noise, more latency; the renderer caps this at 100 ms to keep the statusline hot path bounded. |
| `[cpu] load_glyphs` | `["○","▁","▄","▆","◆"]` | Glyphs for idle→critical load stages. Color is applied to the glyph only. Filled by the active theme; override by writing this key explicitly. |
| `[pulse] pulse_on_threshold` | `90` | CPU% at which the critical glyph starts breathing. |
| `[pulse] pulse_off_threshold` | `80` | CPU% below which the breath turns off (hysteresis). |
| `[pulse] pulse_period_seconds` | `30` | One full breath cycle in seconds. Keep `period / interval_seconds >= 6` for smooth animation. |
| `[pulse] pulse_style` | `"calm"` | Pulse animation style when active. `"calm"` = theme's `pulse_palette` luminance breath, hue-invariant (most subtle). `"flash"` = same `pulse_palette` endpoints, sharper midpoint contrast. `"hue"` = hue-wheel cycling (rainbow shimmer). `"swap"` = hue cycling + glyph shape alternation (most eye-catching). See [Pulse styles](#pulse-styles). |
| `[chain] chain_command` | `""` | Populated by `install`. The command that runs alongside understatus. |
| `[chain] order` | `"self_first"` | `"self_first"` or `"chain_first"` — which output appears on the left. |
| `[chain] chain_cache_ttl_seconds` | `10` | How long (s) to cache the chained command's stdout before re-spawning it. |
| `[chain] chain_timeout_ms` | `500` | Max ms to wait for the chained command. On timeout, cached or empty output is used. |
| `[display] max_width` | `80` | Maximum character width. Lower-priority segments are omitted when exceeded. |
| `[display] show_model` | `true` | Show Claude model name. |
| `[display] show_cost` | `true` | Show cumulative session cost. |
| `[display] show_context` | `true` | Show context usage %. Omitted automatically when null. |
| `[display] show_git` | `true` | Show git branch (Claude workspace path, or lterm/codex `cwd` walk-up when available). |
| `[display] show_session` | `true` | Show lterm/codex session/pane label such as `codex/%3` when supplied by the input payload. |
| `[display] show_battery` | `true` | Show battery (IOKit, 30 s TTL cache). Silently omitted on desktops. |
| `[display] show_disk` | `true` | Show disk usage via `statfs("/")`. |
| `[display] show_network` | `true` | Show network throughput (getifaddrs counter delta). First render has no delta — omitted silently. |
| `[display] show_rate_limit` | `true` | Show Claude Code 5h/weekly rate-limit usage when `rate_limits` is present in stdin. Codex 5h/weekly usage is shown from Codex session enrichment when available. |
| `[display] rate_limit_warn_threshold` | not set | Optional percent threshold. When set, Claude rate-limit values at or above the threshold are tinted with the critical color. |
| `[color] mode` | `"auto"` | `"auto"` \| `"truecolor"` \| `"256"` \| `"none"`. Respects `NO_COLOR`. |
| `[color] band_tints` | see below | Five hex colors for idle→critical glyph tint. Filled by the active theme; override by writing this key explicitly. |
| `[color] pulse_palette` | `["#b87848","#7a5030"]` | High/low brightness endpoints for the breath animation. Filled by the active theme; override by writing this key explicitly. |
| `[color] label_color` | `"#6b7280"` | Dimmed color for labels, units, arrows, and git marker. |
| `[color] separator` | `" · "` | Segment separator string. |
| `[color] separator_color` | `"#3b4048"` | Color for separator and HUD seam. |
| `[color] hud_seam` | `"│"` | Character placed between understatus output and the chained command output. |
| `[refresh] interval_seconds` | `5` | Value written to `settings.json` as `refreshInterval`. Set via `install --interval` or the interactive prompt. On reinstall the existing value is inherited unless `--interval` overrides it. ⚠️ Global side-effect — see above. |
| `[codex] enabled` | `true` | Enable best-effort Codex session enrichment for `--source lterm` / `--source codex` payloads whose agent looks like Codex. |
| `[codex] freshness_minutes` | `240` | Only consider Codex rollout files modified within this many minutes. |
| `[codex] scan_days` | `3` | Scan only this many recent Codex session date directories to keep `~/.codex` reads bounded. |
| `[context] hold_ttl_seconds` | `180` | How long (s) to hold the previous native context % when Claude Code omits `used_percentage`. Lower = faster tracking of the real value; too low and ctx can briefly blank out when both native and token counts are 0. `0` disables hold. |
| `[context] drop_tolerance` | `12` | Downward threshold (percentage points) for breaking the hold and switching to the token fallback. The fallback must be at least this far below the held native to count as a real drop (e.g. `/compact`). ⚠️ Lowering below 12 can reintroduce flicker from the native↔token denominator gap (observed 86↔98 = 12 pp). |

**Default `band_tints`** (cool blue-grey brightness ladder, warm terracotta only at critical):

```toml
band_tints = ["#5a6878", "#6d8296", "#86a0b4", "#9fbfce", "#b87848"]
```

---

## How it works

```
Claude Code  (every refreshInterval seconds)
   │  stdin: one JSON line
   ▼
understatus binary  (new process per call — no daemon, no state files, no locks)
   ├─ read bounded stdin (1 MiB) → parse into ClaudeInput/lterm payload
   ├─ load bounded config (256 KiB; invalid/oversized = defaults)
   ├─ optional Codex enrich (`--source lterm|codex`, bounded ~/.codex scan)
   ├─ double-sample CPU  → cpu_percent (0–100%, average across all cores)
   │     on failure → loadavg fallback: min(load1 / ncpu × 100, 100)
   ├─ memory (host_statistics64)
   ├─ battery (IOKit, 30 s TTL cache)        ← machine-global; omitted on desktops
   ├─ disk    (statfs("/"))
   ├─ network (getifaddrs counter delta)     ← omitted on first render
   ├─ glyph + band tint (color on glyph only, theme-driven)
   │   at ≥90% CPU → brightness breath on the critical-band glyph
   ├─ chain_command child (TTL cache + 500 ms timeout)
   └─ compose → stdout (single newline)
```

**CPU measurement:** Two macOS `host_processor_info` snapshots are taken ~25 ms apart within the same process invocation. The delta gives true instantaneous utilization — not a smoothed load average. If the syscall fails (rare), `loadavg` serves as a silent fallback. User-configured sample windows are capped at 100 ms so a statusline render cannot be delayed indefinitely by config.

**Claude rate limits:** When Claude Code includes `rate_limits` in its statusLine stdin payload, understatus renders the 5h/weekly usage percent and reset countdown without making network calls. The segment is gated by `[display].show_rate_limit` and can be optionally tinted via `[display].rate_limit_warn_threshold`.

**Glyph + tint design (COLOR-ONCE):** `band_tints[0..3]` are cool blue-grey values of increasing brightness (idle to high load). `band_tints[4]` is the lone warm color — terracotta — reserved for the critical stage. Only the glyph character receives color; all numeric values and labels stay uncolored. The active theme fills these colors; individual config keys override the preset.

**Pulse animation:** When CPU stays at or above `pulse_on_threshold` (default 90%), the critical-band glyph animates according to `pulse_style`. The `"calm"` style cycles between `pulse_palette[0]` (brighter) and `pulse_palette[1]` (dimmer) with hue-invariant brightness breathing. `"flash"` uses the same theme `pulse_palette` endpoints but a sharper curve (punchier breathing). `"hue"` rotates through the full hue wheel. `"swap"` adds glyph shape alternation on top of hue rotation. The pulse stays ON until CPU drops below `pulse_off_threshold` (default 80%) — keeping the animation going briefly during cool-down to avoid boundary flicker. Smooth animation requires `pulse_period / interval_seconds >= 6` (6 or more render frames per cycle). See [Pulse styles](#pulse-styles).

**Session cache isolation:** Per-render caches (chain command output, pulse state, network counter delta) are keyed by `session_id`. Multiple terminal windows running understatus simultaneously do not share or corrupt each other's cached values. Battery state is machine-global and is shared across sessions.

---

## CLI Support Matrix

| CLI | Status | Notes |
|-----|--------|-------|
| **Claude Code** | ✅ Full support | Custom `statusLine.command`, stdin JSON, `refreshInterval`, chain preservation, and Claude `rate_limits` rendering are supported. |
| **lterm / cmux** | ✅ Native pill surface | `understatus render --source lterm --surface-format cmux-status` emits one-line JSON for cmux status pills. The plain lterm path can also use `--source lterm --oneline`. |
| **Codex CLI (standalone)** | ⚠️ Manual/tmux path | Codex has a built-in `[tui].status_line` item list, not a Claude-style command hook. For tmux or shell status integrations, feed a small JSON payload to `understatus render --source codex --oneline`; understatus then enriches from `~/.codex` on a best-effort basis. |
| **Gemini CLI** | ⏳ Forward-looking | `/footer` and `/statusline` expose built-in items only; custom command-backed statuslines are not supported by understatus today. |

Examples:

```bash
# Codex tmux-style one-line text
printf '{"agent":"codex","cwd":"%s"}' "$PWD" | understatus render --source codex --oneline

# lterm cmux native status pills (JSON, no ANSI)
printf '{"source":"lterm","session":"codex","pane":"%%3","cwd":"%s","agent":"codex"}' "$PWD" \
  | understatus render --source lterm --surface-format cmux-status
```

For tmux status bars, prefer `color.mode = "none"` and let tmux apply its own `#[fg=...]` styling if raw ANSI SGR is not desired.

---

## Platform

- **macOS only.** Uses `host_processor_info`, `host_statistics64`, and `IOPSCopyPowerSourcesInfo` — all macOS-specific APIs.
- **Apple Silicon (arm64) + Intel (x86\_64).** Tested on macOS arm64 with a 12-core Apple Silicon chip.
- Linux: builds may succeed, but understatus is not a supported Linux target; macOS-specific metrics may degrade or be omitted.
- **Rust edition 2021, MSRV 1.75+.**

---

## License

MIT — see [LICENSE](LICENSE).

---

## 한국어 안내

macOS용 AI 코딩 CLI statusline 애드온입니다. CPU%, 메모리, 배터리, 디스크, 네트워크, AI 세션 정보(모델명·비용·컨텍스트·rate-limit)를 Claude Code 하단 표시줄에 조용하고 자연스럽게 표시합니다.

**주요 특징**

- **9종 테마** — `calm`(기본), `mono`, `vivid`, `ember`, `emoji`, `neon`, `aurora`, `sunset`, `spectrum`. 테마는 8개 시각 키(글리프·색상 등)를 한 번에 설정하며, 개별 키를 config.toml에 명시하면 테마보다 우선합니다.
- **COLOR-ONCE 원칙** — 색은 글리프 문자에만 적용. 숫자 값(CPU%, 비용 등)은 항상 무색.
- **≥90% 호흡** — CPU가 90% 이상으로 유지되면 임계 밴드 글리프가 테라코타 명도로 천천히 숨쉽니다(hue 변화 없음). 부드러운 애니메이션에는 `pulse_period / interval_seconds >= 6` 조건이 필요하며, 위반 시 설치 시점에 경고가 출력됩니다.
- **반응형 CPU** — 매 렌더마다 두 스냅샷(~25ms 간격)을 직접 측정합니다. loadavg가 아닙니다.
- **비파괴 설치** — 기존 `statusLine.command`를 체이닝으로 보존하고 정확히 복원합니다.
- **세션 캐시 격리** — 체인 출력·펄스 상태·네트워크 델타 캐시는 `session_id`별로 분리되어 여러 터미널을 동시에 열어도 값이 섞이지 않습니다. 배터리는 머신 전역.
- **Claude rate-limit 표시** — Claude Code stdin에 `rate_limits`가 들어오면 5h/weekly 사용률과 리셋 카운트다운을 네트워크 호출 없이 표시합니다.
- **lterm/cmux·Codex 경로** — `--source lterm --surface-format cmux-status`는 cmux pill JSON을 출력하고, `--source codex --oneline`은 tmux나 셸 status 연동 환경에서 `~/.codex`를 best-effort로 보강합니다.

**설치**

```bash
# Homebrew
brew install ictechgy/understatus/understatus

# Cargo
cargo install understatus

# npm
npm install -g understatus
```

**Claude Code에 적용**

```bash
understatus install [--interval N] [--theme NAME] [--yes]
understatus uninstall   # 원상 복원
```

Codex를 tmux status에서 직접 쓰는 경우:

```bash
printf '{"agent":"codex","cwd":"%s"}' "$PWD" | understatus render --source codex --oneline
```

`--interval`/`--theme` 미지정 + TTY 환경이면 각 항목을 대화형으로 묻습니다. `--yes`(또는 비TTY)이면 플래그·기존값·기본값을 그대로 사용합니다. 재설치 시 `--interval`을 지정하지 않으면 기존 `config.toml`의 interval이 그대로 승계됩니다(기본 5초로 초기화되지 않습니다).

> ⚠️ `install`은 `settings.json`에 `"refreshInterval": N`을 전역 주입합니다. 체이닝된 기존 명령도 N초마다 재실행 대상이 됩니다. 배터리 절약이 필요하면 `config.toml`에서 `interval_seconds = 10`으로 올리세요.

**테마 관리**

```bash
understatus theme vivid    # 테마 전환 (config.toml만 수정, 즉시 적용)
understatus theme          # 현재 테마 및 사용법 확인
understatus themes         # 사용 가능한 테마 목록
```

| 이름 | 글리프 램프 (idle → crit) | 설명 |
|------|--------------------------|------|
| `calm` | `○ ▁ ▄ ▆ ◆` | 차가운 blue-grey + 테라코타 호흡 (기본) |
| `mono` | `○ ▁ ▄ ▆ ◆` | 무채색, 제로 색상 |
| `vivid` | `░ ▒ ▓ █ █` | 신호등 색 + 블록 글리프 |
| `ember` | `· ∙ • ● ◉` | 따뜻한 앰버/테라코타 단색 + 도트 글리프 |
| `emoji` | `😌 🙂 😅 🥵 🔥` | 이모지 표정 램프 (각 글리프 2칸 폭) |
| `neon` | `░ ▒ ▓ █ █` | 네온 사이버펑크 (일렉트릭 시안→마젠타, hue 순환 펄스) |
| `aurora` | `▁ ▃ ▅ ▆ █` | 오로라 청록→보라 그라데이션 (flash 펄스) |
| `sunset` | `· ∙ • ● ◉` | 노을 골드→코랄→퍼플 (flash 펄스) |
| `spectrum` | `▁ ▂ ▄ ▆ █` | 밴드별 무지개 (초록→마젠타, hue 순환 펄스) |

**펄스 스타일**

CPU가 `pulse_on_threshold`(기본 90%) 이상이면 임계 밴드 글리프가 `pulse_style`에 따라 애니메이션됩니다.

| 스타일 | 동작 |
|--------|------|
| `calm` | 글리프 고정. 테라코타 명도 호흡 (hue 변화 없음). 가장 차분함. **기존 테마 기본.** |
| `flash` | 글리프 고정. 해당 테마의 `pulse_palette` 끝점(`calm` 호흡과 동일한 high/low 색)을 사용하되 더 가파른 사인 곡선 적용 — 중간 위상 대비가 더 강렬함. |
| `hue` | 글리프 고정. 글리프 색이 한 주기(pulse_period_seconds) 동안 색상환 전체를 순환 (무지개 shimmer). |
| `swap` | `hue` 순환 **+** 글리프 모양 교대: 주기 후반부에 `◆`↔`◇` 등 채움/빈 형태를 번갈아 표시. 가장 눈에 띔. |

화려한 테마 기본: `neon`·`spectrum` = `hue`, `aurora`·`sunset` = `flash`. 기존 5종은 모두 `calm`. 개별 키로 재정의 가능.

펄스가 OFF(CPU < `pulse_off_threshold`)이면 스타일과 무관하게 정적 밴드 틴트로 표시됩니다(애니메이션 없음).

```toml
# ~/.config/understatus/config.toml
[pulse]
pulse_on_threshold  = 90   # 펄스 발동 CPU% (기본)
pulse_off_threshold = 80   # 펄스 해제 CPU% — 히스테리시스 (기본)
pulse_style = "hue"        # calm | flash | hue | swap
```

펄스는 CPU가 `pulse_on_threshold`(90)에 도달하면 켜지고, `pulse_off_threshold`(80) 미만으로 떨어질 때까지 유지됩니다 — 냉각 중에도 잠시 애니메이션이 지속되어 경계에서 깜빡임을 방지합니다.

```bash
understatus pulse hue    # 펄스 스타일 변경 (config.toml만 수정, 즉시 적용)
understatus pulse        # 현재 펄스 스타일 확인
```

설정 파일: `~/.config/understatus/config.toml` (없으면 모두 기본값)

```toml
theme = "vivid"   # 한 줄로 테마 지정; 개별 키 override 가능
```

macOS 전용 · Apple Silicon(arm64) + Intel(x86\_64) · Rust 1.75+ · MIT 라이선스