cc-context-stats 1.7.0 → 1.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/package.json +9 -1
  2. package/scripts/context-stats.sh +1 -1
  3. package/scripts/statusline.js +128 -18
  4. package/.editorconfig +0 -60
  5. package/.eslintrc.json +0 -35
  6. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -49
  7. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -31
  8. package/.github/PULL_REQUEST_TEMPLATE.md +0 -33
  9. package/.github/dependabot.yml +0 -44
  10. package/.github/workflows/ci.yml +0 -294
  11. package/.github/workflows/release.yml +0 -151
  12. package/.pre-commit-config.yaml +0 -74
  13. package/.prettierrc +0 -33
  14. package/.shellcheckrc +0 -10
  15. package/CHANGELOG.md +0 -163
  16. package/CLAUDE.md +0 -66
  17. package/CODE_OF_CONDUCT.md +0 -59
  18. package/CONTRIBUTING.md +0 -240
  19. package/RELEASE_NOTES.md +0 -19
  20. package/SECURITY.md +0 -44
  21. package/TODOS.md +0 -72
  22. package/assets/logo/favicon.svg +0 -19
  23. package/assets/logo/logo-black.svg +0 -24
  24. package/assets/logo/logo-full.svg +0 -40
  25. package/assets/logo/logo-icon.svg +0 -27
  26. package/assets/logo/logo-mark.svg +0 -28
  27. package/assets/logo/logo-white.svg +0 -24
  28. package/assets/logo/logo-wordmark.svg +0 -6
  29. package/config/settings-example.json +0 -7
  30. package/config/settings-node.json +0 -7
  31. package/config/settings-python.json +0 -7
  32. package/docs/ARCHITECTURE.md +0 -128
  33. package/docs/CSV_FORMAT.md +0 -42
  34. package/docs/DEPLOYMENT.md +0 -71
  35. package/docs/DEVELOPMENT.md +0 -161
  36. package/docs/configuration.md +0 -118
  37. package/docs/context-stats.md +0 -143
  38. package/docs/installation.md +0 -255
  39. package/docs/scripts.md +0 -140
  40. package/docs/troubleshooting.md +0 -278
  41. package/images/claude-statusline-token-graph.gif +0 -0
  42. package/images/claude-statusline.png +0 -0
  43. package/images/context-status-dumbzone.png +0 -0
  44. package/images/context-status.png +0 -0
  45. package/images/statusline-detail.png +0 -0
  46. package/images/token-graph.jpeg +0 -0
  47. package/images/token-graph.png +0 -0
  48. package/images/v1.6.1.png +0 -0
  49. package/install +0 -351
  50. package/install.sh +0 -298
  51. package/jest.config.js +0 -11
  52. package/pyproject.toml +0 -115
  53. package/requirements-dev.txt +0 -12
  54. package/scripts/statusline-full.sh +0 -304
  55. package/scripts/statusline-git.sh +0 -88
  56. package/scripts/statusline-minimal.sh +0 -67
  57. package/scripts/statusline.py +0 -485
  58. package/src/claude_statusline/__init__.py +0 -11
  59. package/src/claude_statusline/__main__.py +0 -6
  60. package/src/claude_statusline/cli/__init__.py +0 -1
  61. package/src/claude_statusline/cli/context_stats.py +0 -512
  62. package/src/claude_statusline/cli/explain.py +0 -228
  63. package/src/claude_statusline/cli/statusline.py +0 -169
  64. package/src/claude_statusline/core/__init__.py +0 -1
  65. package/src/claude_statusline/core/colors.py +0 -124
  66. package/src/claude_statusline/core/config.py +0 -148
  67. package/src/claude_statusline/core/git.py +0 -78
  68. package/src/claude_statusline/core/state.py +0 -323
  69. package/src/claude_statusline/formatters/__init__.py +0 -1
  70. package/src/claude_statusline/formatters/layout.py +0 -67
  71. package/src/claude_statusline/formatters/time.py +0 -50
  72. package/src/claude_statusline/formatters/tokens.py +0 -70
  73. package/src/claude_statusline/graphs/__init__.py +0 -1
  74. package/src/claude_statusline/graphs/renderer.py +0 -366
  75. package/src/claude_statusline/graphs/statistics.py +0 -92
  76. package/src/claude_statusline/ui/__init__.py +0 -1
  77. package/src/claude_statusline/ui/icons.py +0 -93
  78. package/src/claude_statusline/ui/waiting.py +0 -62
  79. package/tests/bash/test_delta_parity.bats +0 -199
  80. package/tests/bash/test_install.bats +0 -29
  81. package/tests/bash/test_parity.bats +0 -315
  82. package/tests/bash/test_statusline_full.bats +0 -139
  83. package/tests/bash/test_statusline_git.bats +0 -42
  84. package/tests/bash/test_statusline_minimal.bats +0 -37
  85. package/tests/fixtures/json/comma_in_path.json +0 -31
  86. package/tests/fixtures/json/high_usage.json +0 -17
  87. package/tests/fixtures/json/low_usage.json +0 -17
  88. package/tests/fixtures/json/medium_usage.json +0 -17
  89. package/tests/fixtures/json/valid_full.json +0 -30
  90. package/tests/fixtures/json/valid_minimal.json +0 -9
  91. package/tests/node/rotation.test.js +0 -89
  92. package/tests/node/statusline.test.js +0 -240
  93. package/tests/python/conftest.py +0 -84
  94. package/tests/python/test_colors.py +0 -105
  95. package/tests/python/test_config_colors.py +0 -78
  96. package/tests/python/test_data_pipeline.py +0 -446
  97. package/tests/python/test_explain.py +0 -177
  98. package/tests/python/test_icons.py +0 -152
  99. package/tests/python/test_layout.py +0 -127
  100. package/tests/python/test_state_rotation_validation.py +0 -232
  101. package/tests/python/test_statusline.py +0 -215
  102. package/tests/python/test_waiting.py +0 -127
@@ -1,19 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16">
2
- <defs>
3
- <linearGradient id="fav-grad" x1="0%" y1="0%" x2="100%" y2="0%">
4
- <stop offset="0%" stop-color="#22C55E"/>
5
- <stop offset="50%" stop-color="#E9AB34"/>
6
- <stop offset="100%" stop-color="#EF4444"/>
7
- </linearGradient>
8
- </defs>
9
-
10
- <!-- Background -->
11
- <rect width="16" height="16" rx="3" fill="#1A1A1A"/>
12
-
13
- <!-- Simplified wave for 16x16 -->
14
- <path d="M 2 12 C 4 12, 5 10, 7 8 C 9 6, 10 4, 12 3 C 13 2, 14 3, 14 2.5"
15
- stroke="url(#fav-grad)" stroke-width="1.5" fill="none" stroke-linecap="round"/>
16
-
17
- <!-- Dot -->
18
- <circle cx="12" cy="3" r="1.5" fill="#E9AB34"/>
19
- </svg>
@@ -1,24 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 360 72" width="360" height="72">
2
- <!-- Black version for light backgrounds — no background rectangle -->
3
-
4
- <!-- Mark: Context wave -->
5
- <g transform="translate(8, 4)">
6
- <path d="M 10 48 C 16 48, 18 42, 22 40 C 26 38, 28 36, 32 32 C 36 28, 38 22, 42 18 C 46 14, 50 16, 54 14"
7
- stroke="#1A1A1A" stroke-width="3.5" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
8
- <path d="M 10 52 C 16 52, 18 46, 22 44 C 26 42, 28 40, 32 36 C 36 32, 38 26, 42 22 C 46 18, 50 20, 54 18"
9
- stroke="#1A1A1A" stroke-width="1.5" fill="none" stroke-linecap="round" opacity="0.25"/>
10
- <circle cx="42" cy="18" r="3.5" fill="#1A1A1A"/>
11
- <circle cx="42" cy="18" r="6" fill="#1A1A1A" opacity="0.12"/>
12
- <line x1="10" y1="54" x2="54" y2="54" stroke="#1A1A1A" stroke-width="1" stroke-linecap="round" opacity="0.3"/>
13
- </g>
14
-
15
- <!-- Divider -->
16
- <line x1="76" y1="16" x2="76" y2="56" stroke="#1A1A1A" stroke-width="1" opacity="0.2"/>
17
-
18
- <!-- Wordmark -->
19
- <text x="90" y="35" font-family="'SF Mono', 'JetBrains Mono', 'Fira Code', 'Cascadia Code', monospace" font-size="22" font-weight="700" fill="#1A1A1A" letter-spacing="-0.3">cc-context</text>
20
- <text x="90" y="55" font-family="'SF Mono', 'JetBrains Mono', 'Fira Code', 'Cascadia Code', monospace" font-size="15" font-weight="500" fill="#1A1A1A" letter-spacing="3" opacity="0.6">stats</text>
21
-
22
- <!-- Right accent bar -->
23
- <rect x="348" y="20" width="2" height="32" rx="1" fill="#1A1A1A" opacity="0.35"/>
24
- </svg>
@@ -1,40 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 360 72" width="360" height="72">
2
- <defs>
3
- <linearGradient id="full-wave-grad" x1="0%" y1="0%" x2="100%" y2="0%">
4
- <stop offset="0%" stop-color="#22C55E"/>
5
- <stop offset="50%" stop-color="#E9AB34"/>
6
- <stop offset="100%" stop-color="#EF4444"/>
7
- </linearGradient>
8
- </defs>
9
-
10
- <!-- Background pill -->
11
- <rect width="360" height="72" rx="14" fill="#1A1A1A"/>
12
-
13
- <!-- Mark: Context wave in left area -->
14
- <g transform="translate(8, 4)">
15
- <!-- Context wave -->
16
- <path d="M 10 48 C 16 48, 18 42, 22 40 C 26 38, 28 36, 32 32 C 36 28, 38 22, 42 18 C 46 14, 50 16, 54 14"
17
- stroke="url(#full-wave-grad)" stroke-width="3.5" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
18
-
19
- <!-- Echo line -->
20
- <path d="M 10 52 C 16 52, 18 46, 22 44 C 26 42, 28 40, 32 36 C 36 32, 38 26, 42 22 C 46 18, 50 20, 54 18"
21
- stroke="url(#full-wave-grad)" stroke-width="1.5" fill="none" stroke-linecap="round" opacity="0.3"/>
22
-
23
- <!-- Cursor dot -->
24
- <circle cx="42" cy="18" r="3.5" fill="#E9AB34"/>
25
- <circle cx="42" cy="18" r="6" fill="#E9AB34" opacity="0.15"/>
26
-
27
- <!-- Baseline -->
28
- <line x1="10" y1="54" x2="54" y2="54" stroke="#8B7D6B" stroke-width="1" stroke-linecap="round" opacity="0.4"/>
29
- </g>
30
-
31
- <!-- Divider -->
32
- <line x1="76" y1="16" x2="76" y2="56" stroke="#8B7D6B" stroke-width="1" opacity="0.25"/>
33
-
34
- <!-- Wordmark -->
35
- <text x="90" y="35" font-family="'SF Mono', 'JetBrains Mono', 'Fira Code', 'Cascadia Code', monospace" font-size="22" font-weight="700" fill="#FFFFFF" letter-spacing="-0.3">cc-context</text>
36
- <text x="90" y="55" font-family="'SF Mono', 'JetBrains Mono', 'Fira Code', 'Cascadia Code', monospace" font-size="15" font-weight="500" fill="#E9AB34" letter-spacing="3">stats</text>
37
-
38
- <!-- Right accent bar -->
39
- <rect x="348" y="20" width="2" height="32" rx="1" fill="#E9AB34" opacity="0.5"/>
40
- </svg>
@@ -1,27 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="512" height="512">
2
- <defs>
3
- <linearGradient id="icon-wave-grad" x1="0%" y1="0%" x2="100%" y2="0%">
4
- <stop offset="0%" stop-color="#22C55E"/>
5
- <stop offset="50%" stop-color="#E9AB34"/>
6
- <stop offset="100%" stop-color="#EF4444"/>
7
- </linearGradient>
8
- </defs>
9
-
10
- <!-- Background -->
11
- <rect width="512" height="512" rx="96" fill="#1A1A1A"/>
12
-
13
- <!-- Context wave (scaled up) -->
14
- <path d="M 96 376 C 144 376, 160 328, 192 312 C 224 296, 240 280, 272 248 C 304 216, 320 168, 352 136 C 384 104, 400 120, 432 104"
15
- stroke="url(#icon-wave-grad)" stroke-width="24" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
16
-
17
- <!-- Echo line -->
18
- <path d="M 96 408 C 144 408, 160 360, 192 344 C 224 328, 240 312, 272 280 C 304 248, 320 200, 352 168 C 384 136, 400 152, 432 136"
19
- stroke="url(#icon-wave-grad)" stroke-width="10" fill="none" stroke-linecap="round" opacity="0.25"/>
20
-
21
- <!-- Cursor dot -->
22
- <circle cx="352" cy="136" r="28" fill="#E9AB34"/>
23
- <circle cx="352" cy="136" r="48" fill="#E9AB34" opacity="0.12"/>
24
-
25
- <!-- Baseline -->
26
- <line x1="96" y1="424" x2="432" y2="424" stroke="#8B7D6B" stroke-width="6" stroke-linecap="round" opacity="0.35"/>
27
- </svg>
@@ -1,28 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64">
2
- <defs>
3
- <linearGradient id="wave-grad" x1="0%" y1="0%" x2="100%" y2="0%">
4
- <stop offset="0%" stop-color="#22C55E"/>
5
- <stop offset="50%" stop-color="#E9AB34"/>
6
- <stop offset="100%" stop-color="#EF4444"/>
7
- </linearGradient>
8
- </defs>
9
-
10
- <!-- Background -->
11
- <rect width="64" height="64" rx="14" fill="#1A1A1A"/>
12
-
13
- <!-- Context wave: a flowing curve rising from left (low usage) to right (high usage) -->
14
- <!-- This represents the context growth graph - the core concept of the tool -->
15
- <path d="M 10 48 C 16 48, 18 42, 22 40 C 26 38, 28 36, 32 32 C 36 28, 38 22, 42 18 C 46 14, 50 16, 54 14"
16
- stroke="url(#wave-grad)" stroke-width="3.5" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
17
-
18
- <!-- Secondary pulse line (echo effect for depth) -->
19
- <path d="M 10 52 C 16 52, 18 46, 22 44 C 26 42, 28 40, 32 36 C 36 32, 38 26, 42 22 C 46 18, 50 20, 54 18"
20
- stroke="url(#wave-grad)" stroke-width="1.5" fill="none" stroke-linecap="round" opacity="0.3"/>
21
-
22
- <!-- Cursor dot at the "current position" on the wave -->
23
- <circle cx="42" cy="18" r="3.5" fill="#E9AB34"/>
24
- <circle cx="42" cy="18" r="6" fill="#E9AB34" opacity="0.15"/>
25
-
26
- <!-- Baseline -->
27
- <line x1="10" y1="54" x2="54" y2="54" stroke="#8B7D6B" stroke-width="1" stroke-linecap="round" opacity="0.4"/>
28
- </svg>
@@ -1,24 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 360 72" width="360" height="72">
2
- <!-- White version for dark backgrounds — no background rectangle -->
3
-
4
- <!-- Mark: Context wave -->
5
- <g transform="translate(8, 4)">
6
- <path d="M 10 48 C 16 48, 18 42, 22 40 C 26 38, 28 36, 32 32 C 36 28, 38 22, 42 18 C 46 14, 50 16, 54 14"
7
- stroke="#FFFFFF" stroke-width="3.5" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
8
- <path d="M 10 52 C 16 52, 18 46, 22 44 C 26 42, 28 40, 32 36 C 36 32, 38 26, 42 22 C 46 18, 50 20, 54 18"
9
- stroke="#FFFFFF" stroke-width="1.5" fill="none" stroke-linecap="round" opacity="0.25"/>
10
- <circle cx="42" cy="18" r="3.5" fill="#FFFFFF"/>
11
- <circle cx="42" cy="18" r="6" fill="#FFFFFF" opacity="0.12"/>
12
- <line x1="10" y1="54" x2="54" y2="54" stroke="#FFFFFF" stroke-width="1" stroke-linecap="round" opacity="0.3"/>
13
- </g>
14
-
15
- <!-- Divider -->
16
- <line x1="76" y1="16" x2="76" y2="56" stroke="#FFFFFF" stroke-width="1" opacity="0.2"/>
17
-
18
- <!-- Wordmark -->
19
- <text x="90" y="35" font-family="'SF Mono', 'JetBrains Mono', 'Fira Code', 'Cascadia Code', monospace" font-size="22" font-weight="700" fill="#FFFFFF" letter-spacing="-0.3">cc-context</text>
20
- <text x="90" y="55" font-family="'SF Mono', 'JetBrains Mono', 'Fira Code', 'Cascadia Code', monospace" font-size="15" font-weight="500" fill="#FFFFFF" letter-spacing="3" opacity="0.7">stats</text>
21
-
22
- <!-- Right accent bar -->
23
- <rect x="348" y="20" width="2" height="32" rx="1" fill="#FFFFFF" opacity="0.4"/>
24
- </svg>
@@ -1,6 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 260 52" width="260" height="52">
2
- <!-- Wordmark only — transparent background -->
3
- <!-- "cc-context" bold, "stats" in golden amber below -->
4
- <text x="0" y="30" font-family="'SF Mono', 'JetBrains Mono', 'Fira Code', 'Cascadia Code', monospace" font-size="24" font-weight="700" fill="#1A1A1A" letter-spacing="-0.3">cc-context</text>
5
- <text x="0" y="48" font-family="'SF Mono', 'JetBrains Mono', 'Fira Code', 'Cascadia Code', monospace" font-size="15" font-weight="500" fill="#E9AB34" letter-spacing="3">stats</text>
6
- </svg>
@@ -1,7 +0,0 @@
1
- {
2
- "statusLine": {
3
- "type": "command",
4
- "command": "~/.claude/statusline.sh",
5
- "padding": 0
6
- }
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "statusLine": {
3
- "type": "command",
4
- "command": "~/.claude/statusline.js",
5
- "padding": 0
6
- }
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "statusLine": {
3
- "type": "command",
4
- "command": "~/.claude/statusline.py",
5
- "padding": 0
6
- }
7
- }
@@ -1,128 +0,0 @@
1
- # Architecture
2
-
3
- ## Overview
4
-
5
- cc-context-stats provides real-time context monitoring for Claude Code sessions. It consists of two main components:
6
-
7
- 1. **Status Line** - A compact one-line display integrated into Claude Code's UI
8
- 2. **Context Stats CLI** - A live terminal dashboard with ASCII graphs
9
-
10
- ## System Architecture
11
-
12
- ```mermaid
13
- graph TD
14
- CC[Claude Code Host] -->|JSON stdin| SL[Statusline Script]
15
- SL -->|stdout text| CC
16
- SL -->|writes CSV| SF[State Files<br/>~/.claude/statusline/]
17
- SF -->|reads CSV| CS[Context Stats CLI]
18
- CF[Config File<br/>~/.claude/statusline.conf] -->|reads| SL
19
- GIT[Git Repository] -->|branch/status| SL
20
- ```
21
-
22
- ```
23
- ┌─────────────┐ JSON stdin ┌──────────────────┐
24
- │ Claude Code │ ──────────────────> │ Statusline Script │
25
- │ (host) │ <────────────────── │ (sh/py/js) │
26
- └─────────────┘ stdout text └──────┬───────────┘
27
- │ writes
28
-
29
- ┌──────────────────┐
30
- │ State Files │
31
- │ ~/.claude/ │
32
- │ statusline/ │
33
- └──────┬───────────┘
34
- │ reads
35
-
36
- ┌──────────────────┐
37
- │ Context Stats CLI │
38
- │ (Python/Bash) │
39
- └──────────────────┘
40
- ```
41
-
42
- ## Component Details
43
-
44
- ### Status Line Scripts
45
-
46
- Three implementation languages with identical output:
47
-
48
- | Script | Language | Dependencies | State Writes |
49
- | ---------------------- | ---------- | ------------ | ------------ |
50
- | `statusline-full.sh` | Bash | `jq` | No |
51
- | `statusline-git.sh` | Bash | `jq` | No |
52
- | `statusline-minimal.sh`| Bash | `jq` | No |
53
- | `statusline.py` | Python 3 | None | Yes |
54
- | `statusline.js` | Node.js 18+| None | Yes |
55
-
56
- > **Note:** Only the Python and Node.js scripts write state files. The bash scripts provide status line display only, without persisting data for the context-stats CLI.
57
-
58
- **Data flow:**
59
- 1. Claude Code pipes JSON state via stdin on each refresh
60
- 2. Script parses model info, context tokens, session data
61
- 3. Script reads `~/.claude/statusline.conf` for user preferences
62
- 4. Script checks git status for branch/changes info (5-second timeout)
63
- 5. Python/Node.js scripts write state to `~/.claude/statusline/<session_id>.state`
64
- 6. Script outputs formatted ANSI text to stdout
65
-
66
- ### Context Stats CLI
67
-
68
- Two implementations of the live dashboard:
69
-
70
- | Script | Language | Install Method |
71
- | ------------------ | -------- | ------------------------- |
72
- | `context-stats.sh` | Bash | Shell installer |
73
- | `context_stats.py` | Python | `pip install cc-context-stats` |
74
-
75
- The Python CLI (installed via pip or npm) is the primary implementation, providing live ASCII graphs with zone awareness. The bash script is a standalone alternative installed by the shell installer.
76
-
77
- ### Python Package (`src/claude_statusline/`)
78
-
79
- The pip-installable package provides both the statusline and context-stats CLI:
80
-
81
- ```
82
- src/claude_statusline/
83
- ├── __init__.py # Package version and exports
84
- ├── __main__.py # python -m claude_statusline entry
85
- ├── cli/
86
- │ ├── statusline.py # claude-statusline entry point
87
- │ └── context_stats.py # context-stats entry point
88
- ├── core/
89
- │ ├── colors.py # ANSI color management
90
- │ ├── config.py # Configuration loading
91
- │ ├── git.py # Git status detection (5s timeout)
92
- │ └── state.py # State file reading/writing/rotation
93
- ├── formatters/
94
- │ ├── layout.py # Output width/layout management
95
- │ ├── time.py # Duration formatting
96
- │ └── tokens.py # Token count formatting
97
- ├── graphs/
98
- │ ├── renderer.py # ASCII graph rendering
99
- │ └── statistics.py # Data statistics
100
- └── ui/
101
- ├── icons.py # Unicode icons
102
- └── waiting.py # Waiting animation
103
- ```
104
-
105
- ### State Files
106
-
107
- State files persist token history between statusline refreshes:
108
-
109
- ```
110
- ~/.claude/statusline/statusline.<session_id>.state
111
- ```
112
-
113
- Each line is a CSV record with 14 comma-separated fields (timestamp, token counts, cost, session metadata, and context metrics). See [CSV_FORMAT.md](CSV_FORMAT.md) for the full field specification. The context-stats CLI reads these files to render graphs.
114
-
115
- **Rotation:** Files are automatically rotated at 10,000 lines, keeping the most recent 5,000 entries. This prevents unbounded file growth during long sessions.
116
-
117
- **Session ID validation:** IDs are validated to reject path-traversal characters (`/`, `\`, `..`, null bytes).
118
-
119
- ## Data Privacy
120
-
121
- All data stays local:
122
- - State files are written to `~/.claude/statusline/`
123
- - No network requests are made
124
- - No telemetry or analytics
125
-
126
- ## Configuration
127
-
128
- User preferences are stored in `~/.claude/statusline.conf` as simple `key=value` pairs. See [Configuration](configuration.md) for details.
@@ -1,42 +0,0 @@
1
- # CSV State File Format
2
-
3
- State files are stored at `~/.claude/statusline/statusline.<session_id>.state`. Each line is a CSV record with 14 comma-separated fields.
4
-
5
- ## Field Specification
6
-
7
- | Index | Field | Type | Description |
8
- |-------|-------|------|-------------|
9
- | 0 | `timestamp` | integer | Unix timestamp in seconds |
10
- | 1 | `total_input_tokens` | integer | Cumulative input tokens for the session |
11
- | 2 | `total_output_tokens` | integer | Cumulative output tokens for the session |
12
- | 3 | `current_input_tokens` | integer | Input tokens for the current request |
13
- | 4 | `current_output_tokens` | integer | Output tokens for the current request |
14
- | 5 | `cache_creation` | integer | Cache creation input tokens |
15
- | 6 | `cache_read` | integer | Cache read input tokens |
16
- | 7 | `cost_usd` | float | Total session cost in USD |
17
- | 8 | `lines_added` | integer | Total lines added in session |
18
- | 9 | `lines_removed` | integer | Total lines removed in session |
19
- | 10 | `session_id` | string | Session identifier (UUID) |
20
- | 11 | `model_id` | string | Model identifier (e.g., `claude-opus-4-5`) |
21
- | 12 | `workspace_project_dir` | string | Project directory path (commas replaced with underscores) |
22
- | 13 | `context_window_size` | integer | Context window size in tokens |
23
-
24
- ## Constraints
25
-
26
- - Fields are separated by commas with no quoting or escaping.
27
- - The `workspace_project_dir` field (index 12) is sanitized before writing: all comma characters (`,`) are replaced with underscores (`_`) to prevent CSV corruption.
28
- - Numeric fields default to `0` when absent. String fields default to empty string.
29
- - Lines are newline-terminated (`\n`).
30
- - Files are append-only.
31
- - Files are automatically rotated at 10,000 lines (keeps most recent 5,000) by the Python and Node.js statusline scripts.
32
- - Duplicate entries (same token count as previous line) are skipped to prevent file bloat.
33
-
34
- ## Legacy Format
35
-
36
- Older state files may contain 2-field lines: `timestamp,total_input_tokens`. The reader defaults all other fields to zero/empty for these lines.
37
-
38
- ## Example
39
-
40
- ```
41
- 1710288000,75000,8500,50000,5000,10000,20000,0.05234,250,45,abc-123-def,claude-opus-4-5,/home/user/my-project,200000
42
- ```
@@ -1,71 +0,0 @@
1
- # Deployment
2
-
3
- ## Distribution Channels
4
-
5
- cc-context-stats is distributed through three channels:
6
-
7
- | Channel | Package Name | Command |
8
- | ------------ | ----------------- | ------------------------------------ |
9
- | Shell script | N/A | `curl -fsSL .../install.sh \| bash` |
10
- | PyPI | `cc-context-stats`| `pip install cc-context-stats` |
11
- | npm | `cc-context-stats`| `npm install -g cc-context-stats` |
12
-
13
- Both pip and npm installs provide the `claude-statusline` and `context-stats` CLI commands.
14
-
15
- ## Publishing to PyPI
16
-
17
- ```bash
18
- # Ensure clean build
19
- rm -rf dist/ build/
20
-
21
- # Build
22
- python -m build
23
-
24
- # Check package
25
- twine check dist/*
26
-
27
- # Upload to PyPI
28
- twine upload dist/*
29
- ```
30
-
31
- ## Publishing to npm
32
-
33
- ```bash
34
- # Verify package.json
35
- npm pack --dry-run
36
-
37
- # Publish
38
- npm publish
39
- ```
40
-
41
- ## Release Workflow
42
-
43
- The project uses GitHub Actions for automated releases (`.github/workflows/release.yml`):
44
-
45
- 1. Update versions in all locations (see Version Management below)
46
- 2. Update `CHANGELOG.md` with the new version entry
47
- 3. Create and push a version tag: `git tag v1.x.x && git push --tags`
48
- 4. The release workflow automatically:
49
- - Runs the full test suite (Python, Node.js, Bash)
50
- - Builds Python and npm packages
51
- - Creates a GitHub Release with release notes
52
-
53
- CI is also run on every push and PR via `.github/workflows/ci.yml`.
54
-
55
- ## Version Management
56
-
57
- Versions must be updated in sync across these files:
58
-
59
- | File | Field |
60
- | --- | --- |
61
- | `pyproject.toml` | `[project] version` |
62
- | `package.json` | `version` |
63
- | `src/claude_statusline/__init__.py` | `__version__` |
64
- | `CHANGELOG.md` | New version entry |
65
- | `RELEASE_NOTES.md` | Current release notes |
66
-
67
- ## Install Script
68
-
69
- The `install.sh` script is fetched directly from the `main` branch on GitHub. Changes to the installer take effect immediately for new users running the curl one-liner.
70
-
71
- The installer embeds the version from `package.json` and the current git commit hash into the installed scripts, preventing version drift between the repository and installed copies.
@@ -1,161 +0,0 @@
1
- # Development Guide
2
-
3
- ## Prerequisites
4
-
5
- - **Git** - Version control
6
- - **jq** - JSON processor (for bash scripts)
7
- - **Python 3.9+** - For Python package and testing
8
- - **Node.js 18+** - For Node.js script and testing
9
- - **Bats** - Bash Automated Testing System (optional, for bash tests)
10
- - **pre-commit** - Git hook framework (optional, for automated code quality)
11
-
12
- ## Setup
13
-
14
- ```bash
15
- # Clone the repository
16
- git clone https://github.com/luongnv89/cc-context-stats.git
17
- cd cc-context-stats
18
-
19
- # Python setup
20
- python3 -m venv venv
21
- source venv/bin/activate
22
- pip install -r requirements-dev.txt
23
- pip install -e ".[dev]"
24
-
25
- # Node.js setup
26
- npm install
27
-
28
- # Install pre-commit hooks (optional but recommended)
29
- pre-commit install
30
- ```
31
-
32
- ## Project Layout
33
-
34
- ```
35
- cc-context-stats/
36
- ├── src/claude_statusline/ # Python package source
37
- │ ├── cli/ # CLI entry points (statusline, context-stats)
38
- │ ├── core/ # Config, state, git, colors
39
- │ ├── formatters/ # Token, time, layout formatting
40
- │ ├── graphs/ # ASCII graph rendering
41
- │ └── ui/ # Icons, waiting animation
42
- ├── scripts/ # Standalone scripts (sh/py/js)
43
- │ ├── statusline-full.sh # Full-featured bash statusline
44
- │ ├── statusline-git.sh # Git-focused bash variant
45
- │ ├── statusline-minimal.sh # Minimal bash variant
46
- │ ├── statusline.py # Python standalone statusline
47
- │ ├── statusline.js # Node.js standalone statusline
48
- │ └── context-stats.sh # Bash context-stats CLI
49
- ├── tests/
50
- │ ├── bash/ # Bats tests
51
- │ ├── python/ # Pytest tests
52
- │ └── node/ # Jest tests
53
- ├── config/ # Configuration examples
54
- ├── docs/ # Documentation
55
- ├── .github/workflows/ # CI/CD (ci.yml, release.yml)
56
- ├── pyproject.toml # Python build config (hatchling)
57
- └── package.json # Node.js config
58
- ```
59
-
60
- ## Running Tests
61
-
62
- ```bash
63
- # Python tests
64
- source venv/bin/activate
65
- pytest tests/python/ -v
66
-
67
- # Node.js tests (Jest)
68
- npm test
69
-
70
- # Bash integration tests
71
- bats tests/bash/*.bats
72
-
73
- # All tests
74
- pytest && npm test && bats tests/bash/*.bats
75
- ```
76
-
77
- ### Coverage Reports
78
-
79
- ```bash
80
- # Python coverage
81
- pytest tests/python/ -v --cov=scripts --cov-report=html
82
-
83
- # Node.js coverage
84
- npm run test:coverage
85
- ```
86
-
87
- ## Linting & Formatting
88
-
89
- ```bash
90
- # Run all checks via pre-commit
91
- pre-commit run --all-files
92
-
93
- # Individual tools
94
- ruff check src/ scripts/statusline.py # Python lint
95
- ruff format src/ scripts/statusline.py # Python format
96
- npx eslint scripts/statusline.js # JavaScript lint
97
- npx prettier --write scripts/statusline.js # JavaScript format
98
- shellcheck scripts/*.sh install.sh # Bash lint
99
- ```
100
-
101
- ## Manual Testing
102
-
103
- ```bash
104
- # Test statusline scripts with mock input
105
- echo '{"model":{"display_name":"Test"},"cwd":"/test","session_id":"abc123","context":{"tokens_remaining":64000,"context_window":200000}}' | python3 scripts/statusline.py
106
-
107
- echo '{"model":{"display_name":"Test"}}' | node scripts/statusline.js
108
-
109
- echo '{"model":{"display_name":"Test"}}' | bash scripts/statusline-full.sh
110
- ```
111
-
112
- ## Building
113
-
114
- ```bash
115
- # Python package
116
- python -m build
117
-
118
- # Verify package
119
- twine check dist/*
120
-
121
- # npm dry run
122
- npm pack --dry-run
123
- ```
124
-
125
- ## Cross-Script Consistency
126
-
127
- All three implementations (bash, Python, Node.js) must produce identical output for the same input. When modifying status line behavior:
128
-
129
- 1. Update all three script variants
130
- 2. Run integration tests to verify parity
131
- 3. Test on multiple platforms if possible
132
-
133
- The delta parity tests (`tests/bash/`) verify that Python and Node.js produce identical deltas for the same CSV state data.
134
-
135
- ## Debugging
136
-
137
- ### State files
138
-
139
- ```bash
140
- # View current state files
141
- ls -la ~/.claude/statusline/statusline.*.state
142
-
143
- # Inspect state content (14 CSV fields per line)
144
- cat ~/.claude/statusline/statusline.<session_id>.state
145
-
146
- # Watch state file updates in real-time
147
- watch -n 1 'tail -5 ~/.claude/statusline/statusline.*.state'
148
- ```
149
-
150
- ### Verbose testing
151
-
152
- ```bash
153
- # Python with verbose output
154
- pytest tests/python/ -v -s
155
-
156
- # Node.js with verbose output
157
- npx jest --verbose
158
-
159
- # Bats with verbose output
160
- bats --verbose-run tests/bash/*.bats
161
- ```