cc-context-stats 1.5.1 → 1.6.0

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.
@@ -0,0 +1,49 @@
1
+ ---
2
+ name: Bug Report
3
+ about: Report a bug to help us improve
4
+ title: '[BUG] '
5
+ labels: bug
6
+ assignees: ''
7
+ ---
8
+
9
+ ## Bug Description
10
+
11
+ A clear and concise description of what the bug is.
12
+
13
+ ## Steps to Reproduce
14
+
15
+ 1. Install cc-context-stats via '...'
16
+ 2. Run '...'
17
+ 3. See error
18
+
19
+ ## Expected Behavior
20
+
21
+ A clear and concise description of what you expected to happen.
22
+
23
+ ## Actual Behavior
24
+
25
+ What actually happened instead.
26
+
27
+ ## Screenshots
28
+
29
+ If applicable, add screenshots to help explain your problem.
30
+
31
+ ## Environment
32
+
33
+ - OS: [e.g., macOS 14.0, Ubuntu 22.04, Windows 11]
34
+ - Shell: [e.g., zsh, bash, PowerShell]
35
+ - cc-context-stats version: [e.g., 1.6.0]
36
+ - Installation method: [npm, pip, shell script]
37
+ - Node.js version: [if applicable]
38
+ - Python version: [if applicable]
39
+ - Claude Code version: [if applicable]
40
+
41
+ ## Additional Context
42
+
43
+ Add any other context about the problem here.
44
+
45
+ ## State File Content (if relevant)
46
+
47
+ ```
48
+ # Paste output of: cat ~/.claude/statusline/statusline.*.state
49
+ ```
@@ -0,0 +1,31 @@
1
+ ---
2
+ name: Feature Request
3
+ about: Suggest an idea for this project
4
+ title: '[FEATURE] '
5
+ labels: enhancement
6
+ assignees: ''
7
+ ---
8
+
9
+ ## Problem Statement
10
+
11
+ A clear and concise description of what the problem is.
12
+ Ex. I'm always frustrated when [...]
13
+
14
+ ## Proposed Solution
15
+
16
+ A clear and concise description of what you want to happen.
17
+
18
+ ## Alternatives Considered
19
+
20
+ A clear and concise description of any alternative solutions or features you've considered.
21
+
22
+ ## Use Cases
23
+
24
+ Describe specific use cases where this feature would be beneficial:
25
+
26
+ 1. Use case 1
27
+ 2. Use case 2
28
+
29
+ ## Additional Context
30
+
31
+ Add any other context, mockups, or screenshots about the feature request here.
@@ -0,0 +1,33 @@
1
+ ## Description
2
+
3
+ Brief description of the changes in this PR.
4
+
5
+ ## Related Issue
6
+
7
+ Fixes #(issue number)
8
+
9
+ ## Type of Change
10
+
11
+ - [ ] Bug fix (non-breaking change which fixes an issue)
12
+ - [ ] New feature (non-breaking change which adds functionality)
13
+ - [ ] Breaking change (fix or feature that would cause existing functionality to change)
14
+ - [ ] Documentation update
15
+ - [ ] Refactoring (no functional changes)
16
+
17
+ ## Checklist
18
+
19
+ - [ ] My code follows the project's style guidelines
20
+ - [ ] I have performed a self-review of my code
21
+ - [ ] I have made corresponding changes to the documentation
22
+ - [ ] My changes generate no new warnings
23
+ - [ ] I have added tests that prove my fix is effective or that my feature works
24
+ - [ ] New and existing unit tests pass locally with my changes
25
+ - [ ] All three implementations (bash, Python, Node.js) produce consistent output (if applicable)
26
+
27
+ ## Screenshots (if applicable)
28
+
29
+ Add screenshots to help explain your changes.
30
+
31
+ ## Additional Notes
32
+
33
+ Any additional information that reviewers should know.
@@ -183,6 +183,42 @@ jobs:
183
183
  flags: node
184
184
  fail_ci_if_error: false
185
185
 
186
+ # ============================================
187
+ # CROSS-IMPLEMENTATION PARITY TESTS
188
+ # ============================================
189
+ parity-test:
190
+ name: Parity Tests (${{ matrix.os }})
191
+ needs: [python-test, node-test]
192
+ runs-on: ${{ matrix.os }}
193
+ strategy:
194
+ fail-fast: false
195
+ matrix:
196
+ os: [ubuntu-latest, macos-latest]
197
+ steps:
198
+ - name: Checkout
199
+ uses: actions/checkout@v4
200
+
201
+ - name: Set up Python
202
+ uses: actions/setup-python@v5
203
+ with:
204
+ python-version: '3.11'
205
+
206
+ - name: Set up Node.js
207
+ uses: actions/setup-node@v4
208
+ with:
209
+ node-version: '20'
210
+
211
+ - name: Install Bats
212
+ run: |
213
+ if [[ "$RUNNER_OS" == "Linux" ]]; then
214
+ sudo apt-get update && sudo apt-get install -y bats
215
+ elif [[ "$RUNNER_OS" == "macOS" ]]; then
216
+ brew install bats-core
217
+ fi
218
+
219
+ - name: Run parity tests
220
+ run: bats tests/bash/test_parity.bats
221
+
186
222
  # ============================================
187
223
  # INTEGRATION TESTS
188
224
  # ============================================
@@ -238,7 +274,7 @@ jobs:
238
274
  # ============================================
239
275
  ci-success:
240
276
  name: CI Success
241
- needs: [bash-lint, bash-test, python-lint, python-test, node-lint, node-test, integration-test]
277
+ needs: [bash-lint, bash-test, python-lint, python-test, node-lint, node-test, integration-test, parity-test]
242
278
  runs-on: ubuntu-latest
243
279
  if: always()
244
280
  steps:
@@ -250,7 +286,8 @@ jobs:
250
286
  [[ "${{ needs.python-test.result }}" != "success" ]] || \
251
287
  [[ "${{ needs.node-lint.result }}" != "success" ]] || \
252
288
  [[ "${{ needs.node-test.result }}" != "success" ]] || \
253
- [[ "${{ needs.integration-test.result }}" != "success" ]]; then
289
+ [[ "${{ needs.integration-test.result }}" != "success" ]] || \
290
+ [[ "${{ needs.parity-test.result }}" != "success" ]]; then
254
291
  echo "One or more jobs failed"
255
292
  exit 1
256
293
  fi
package/CHANGELOG.md CHANGED
@@ -7,22 +7,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.6.0] - 2026-03-13
11
+
10
12
  ### Added
11
13
 
14
+ - **CLI `--version` flag** - `context-stats --version` / `-V` now prints the current version
15
+ - **State file rotation** - Automatic rotation at 10,000 lines (keeps most recent 5,000) to prevent unbounded file growth
16
+ - **Session ID validation** - Rejects path-traversal characters (`/`, `\`, `..`, null bytes) for security
17
+ - **Git command timeout** - 5-second timeout on git operations in both Python and Node.js implementations
18
+ - **Core data pipeline unit tests** - 51 tests across 6 classes covering config, state, formatters, graph, and CLI
19
+ - **Cross-implementation parity test** - Ensures Python and Node.js statusline scripts produce consistent output
20
+ - **Stderr warnings** - Critical error paths now emit warnings to stderr for debugging
21
+ - **CSV format documentation** - Formal specification of the 14-field state file format
22
+ - **Comma guard for workspace paths** - Commas in `workspace_project_dir` are replaced with underscores before CSV write
23
+ - **Open-source standard files** - Added CODE_OF_CONDUCT.md, CONTRIBUTING.md, SECURITY.md, and GitHub issue/PR templates
12
24
  - **NPM Package** - `cc-context-stats` now available on npm for JavaScript/Node.js environments
13
- - Install via `npm install -g cc-context-stats` or `yarn global add cc-context-stats`
14
- - Provides same functionality as Python package for Node.js users
15
- - **Enhanced Documentation** - Updated README with npm installation instructions and badges
16
25
 
17
26
  ### Changed
18
27
 
19
28
  - **Package Metadata** - Synchronized package descriptions across npm and PyPI for consistency
20
- - **Keywords** - Aligned keywords across npm and Python packages for better discoverability
21
29
  - **Installation Section** - Moved shell script installation to the top of README as the recommended method
22
- - **Install Script Documentation** - Enhanced `install.sh` with comprehensive header documentation including:
23
- - Features overview (real-time monitoring, live dashboard, zone detection)
24
- - Requirements (curl, jq)
25
- - Installation destinations and file descriptions
30
+
31
+ ### Dependencies
32
+
33
+ - Bumped prettier from 3.7.4 to 3.8.0
26
34
 
27
35
  ## [1.2.0] - 2025-01-08
28
36
 
package/CLAUDE.md ADDED
@@ -0,0 +1,54 @@
1
+ # CLAUDE.md
2
+
3
+ ## Project Purpose
4
+
5
+ cc-context-stats provides real-time context window monitoring for Claude Code sessions. It tracks token consumption over time and displays live ASCII graphs so users can see how much context remains.
6
+
7
+ ## Dual-Implementation Rationale
8
+
9
+ The statusline is implemented in three languages (Bash, Python, Node.js) so users can choose whichever runtime they have available. Claude Code invokes the statusline script via stdin JSON pipe — any implementation that reads JSON from stdin and writes formatted text to stdout works. The Python and Node.js implementations also persist state to CSV files read by the `context-stats` CLI.
10
+
11
+ ## CSV Format Contract
12
+
13
+ State files are append-only CSV at `~/.claude/statusline/statusline.<session_id>.state` with 14 comma-separated fields. See [docs/CSV_FORMAT.md](docs/CSV_FORMAT.md) for the full field specification. Key constraint: `workspace_project_dir` has commas replaced with underscores before writing.
14
+
15
+ ## Statusline Script Landscape
16
+
17
+ | Script | Language | State writes | Notes |
18
+ |---|---|---|---|
19
+ | `scripts/statusline-full.sh` | Bash | No | Full display, requires `jq` |
20
+ | `scripts/statusline-git.sh` | Bash | No | Git-focused variant |
21
+ | `scripts/statusline-minimal.sh` | Bash | No | Minimal variant |
22
+ | `scripts/statusline.py` | Python 3 | Yes | Pip-installable via package |
23
+ | `scripts/statusline.js` | Node.js | Yes | Standalone script |
24
+
25
+ ## Test Commands
26
+
27
+ ```bash
28
+ # Python tests
29
+ source venv/bin/activate
30
+ pytest tests/python/ -v
31
+
32
+ # Node.js tests
33
+ npm test
34
+
35
+ # Bash integration tests
36
+ bats tests/bash/*.bats
37
+
38
+ # All tests
39
+ pytest && npm test && bats tests/bash/*.bats
40
+ ```
41
+
42
+ ## Key Architectural Decisions
43
+
44
+ - **Append-only CSV state files** with rotation at 10,000 lines (keeps most recent 5,000)
45
+ - **No network requests** — all data stays local in `~/.claude/statusline/`
46
+ - **Session ID validation** — rejects `/`, `\`, `..`, and null bytes for path-traversal defense
47
+ - **5-second git command timeout** in both Python and Node.js implementations
48
+ - **Config via `~/.claude/statusline.conf`** — simple key=value pairs
49
+
50
+ ## Cross-References
51
+
52
+ - [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) — system architecture and data flow
53
+ - [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md) — setup, testing, and contribution guide
54
+ - [docs/CSV_FORMAT.md](docs/CSV_FORMAT.md) — state file field specification
@@ -0,0 +1,59 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ We as members, contributors, and leaders pledge to make participation in our
6
+ community a harassment-free experience for everyone, regardless of age, body
7
+ size, visible or invisible disability, ethnicity, sex characteristics, gender
8
+ identity and expression, level of experience, education, socio-economic status,
9
+ nationality, personal appearance, race, religion, or sexual identity
10
+ and orientation.
11
+
12
+ We pledge to act and interact in ways that contribute to an open, welcoming,
13
+ diverse, inclusive, and healthy community.
14
+
15
+ ## Our Standards
16
+
17
+ Examples of behavior that contributes to a positive environment:
18
+
19
+ * Demonstrating empathy and kindness toward other people
20
+ * Being respectful of differing opinions, viewpoints, and experiences
21
+ * Giving and gracefully accepting constructive feedback
22
+ * Accepting responsibility and apologizing to those affected by our mistakes
23
+ * Focusing on what is best for the overall community
24
+
25
+ Examples of unacceptable behavior:
26
+
27
+ * The use of sexualized language or imagery, and sexual attention or advances
28
+ * Trolling, insulting or derogatory comments, and personal or political attacks
29
+ * Public or private harassment
30
+ * Publishing others' private information without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate
32
+
33
+ ## Enforcement Responsibilities
34
+
35
+ Community leaders are responsible for clarifying and enforcing our standards of
36
+ acceptable behavior and will take appropriate and fair corrective action in
37
+ response to any behavior that they deem inappropriate, threatening, offensive,
38
+ or harmful.
39
+
40
+ ## Scope
41
+
42
+ This Code of Conduct applies within all community spaces, and also applies when
43
+ an individual is officially representing the community in public spaces.
44
+
45
+ ## Enforcement
46
+
47
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
48
+ reported to the community leaders responsible for enforcement at
49
+ luongnv89@gmail.com.
50
+
51
+ All complaints will be reviewed and investigated promptly and fairly.
52
+
53
+ ## Attribution
54
+
55
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
56
+ version 2.0, available at
57
+ https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
58
+
59
+ [homepage]: https://www.contributor-covenant.org
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Nguyen Luong
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -177,9 +177,18 @@ Context Stats hooks into Claude Code's state files to track token usage across y
177
177
  - [Context Stats Guide](docs/context-stats.md) - Detailed usage guide
178
178
  - [Configuration Options](docs/configuration.md) - All settings explained
179
179
  - [Installation Guide](docs/installation.md) - Platform-specific setup
180
+ - [Architecture](docs/ARCHITECTURE.md) - System design and components
181
+ - [Development](docs/DEVELOPMENT.md) - Dev setup and debugging
182
+ - [Deployment](docs/DEPLOYMENT.md) - Publishing and release process
180
183
  - [Troubleshooting](docs/troubleshooting.md) - Common issues
181
184
  - [Changelog](CHANGELOG.md) - Version history
182
185
 
186
+ ## Contributing
187
+
188
+ Contributions are welcome! Please read our [Contributing Guide](CONTRIBUTING.md) for details on the development setup, branching strategy, and PR process.
189
+
190
+ This project follows the [Contributor Covenant Code of Conduct](CODE_OF_CONDUCT.md).
191
+
183
192
  ## Migration from cc-statusline
184
193
 
185
194
  If you were using the previous `cc-statusline` package:
package/RELEASE_NOTES.md CHANGED
@@ -1,10 +1,19 @@
1
- ## v1.5.1 — 2026-03-11
1
+ ## v1.6.0 — 2026-03-13
2
2
 
3
- ### Bug Fixes
4
- - **Fix session ID disappearing from statusline** — Claude Code runs statusline scripts as piped subprocesses with no real TTY, causing terminal width detection to always return 80 columns. This made `fit_to_width()` drop lower-priority parts like session ID even when the real terminal had plenty of space. Now uses 200 columns as default when no TTY is detected; Claude Code's own UI handles overflow.
5
- - **Fix CI failures** — Resolve ESLint, Python 3.9 compatibility, and release workflow issues
3
+ ### Features
4
+ - **CLI `--version` flag** — `context-stats --version` / `-V` now prints the current version
5
+ - **State file rotation** — Automatic rotation at 10,000 lines (keeps most recent 5,000) to prevent unbounded file growth
6
+ - **Session ID validation** — Rejects path-traversal characters (`/`, `\`, `..`, null bytes) for security
7
+ - **Git command timeout** — 5-second timeout on git operations in both Python and Node.js implementations
8
+ - **Core data pipeline unit tests** — 51 tests across 6 classes covering config, state, formatters, graph, and CLI
9
+ - **Cross-implementation parity test** — Ensures Python and Node.js statusline scripts produce consistent output
10
+ - **Stderr warnings** — Critical error paths now emit warnings to stderr for debugging
11
+ - **CSV format documentation** — Formal specification of the 14-field state file format
12
+ - **Comma guard for workspace paths** — Commas in `workspace_project_dir` are replaced with underscores before CSV write
13
+ - **Open-source standard files** — Added CODE_OF_CONDUCT.md, CONTRIBUTING.md, SECURITY.md, and GitHub issue/PR templates
14
+ - **NPM Package** — `cc-context-stats` now available on npm for JavaScript/Node.js environments
6
15
 
7
- ### Other Changes
8
- - Update logo SVG assets
16
+ ### Dependencies
17
+ - Bumped prettier from 3.7.4 to 3.8.0
9
18
 
10
- **Full Changelog**: https://github.com/luongnv89/cc-context-stats/compare/v1.5.0...v1.5.1
19
+ **Full Changelog**: https://github.com/luongnv89/cc-context-stats/compare/v1.5.1...v1.6.0
package/SECURITY.md ADDED
@@ -0,0 +1,44 @@
1
+ # Security Policy
2
+
3
+ ## Supported Versions
4
+
5
+ | Version | Supported |
6
+ | ------- | ------------------ |
7
+ | 1.5.x | :white_check_mark: |
8
+ | < 1.5 | :x: |
9
+
10
+ ## Reporting a Vulnerability
11
+
12
+ We take security vulnerabilities seriously. If you discover a security issue, please report it responsibly.
13
+
14
+ ### How to Report
15
+
16
+ 1. **Do NOT** open a public GitHub issue for security vulnerabilities
17
+ 2. Email your findings to luongnv89@gmail.com
18
+ 3. Include detailed steps to reproduce the vulnerability
19
+ 4. Allow up to 48 hours for an initial response
20
+
21
+ ### What to Include
22
+
23
+ - Type of vulnerability
24
+ - Full paths of affected source files
25
+ - Location of the affected source code (tag/branch/commit or direct URL)
26
+ - Step-by-step instructions to reproduce
27
+ - Proof-of-concept or exploit code (if possible)
28
+ - Impact of the issue
29
+
30
+ ### What to Expect
31
+
32
+ - Acknowledgment of your report within 48 hours
33
+ - Regular updates on our progress
34
+ - Credit in the security advisory (if desired)
35
+ - Notification when the issue is fixed
36
+
37
+ ## Security Best Practices
38
+
39
+ When contributing to this project:
40
+
41
+ - Never commit secrets, API keys, or credentials
42
+ - Use environment variables for sensitive configuration
43
+ - Follow secure coding practices
44
+ - Report any security concerns immediately
package/TODOS.md ADDED
@@ -0,0 +1,72 @@
1
+ # TODOs
2
+
3
+ Items identified from the HOLD SCOPE mega review (2026-03-12).
4
+
5
+ ## P1 — High Priority
6
+
7
+ ### ~~1. Cross-implementation parity test~~ ✅ Done
8
+ **What:** Add a CI integration test that feeds identical JSON to both Python (`statusline.py`) and Node.js (`statusline.js`) scripts and asserts they write identical CSV state lines and produce equivalent stdout.
9
+ **Why:** The two implementations share no code or schema contract. Drift has occurred before and will occur again. This catches it automatically.
10
+ **Effort:** S
11
+ **Depends on:** None
12
+ **Status:** Implemented in `tests/bash/test_parity.bats` with CI job in `.github/workflows/ci.yml`. Archived as `openspec/changes/archive/2026-03-12-cross-impl-parity-test/`.
13
+
14
+ ### ~~2. Document CSV state file format + comma guard~~ ✅ Done
15
+ **What:** Create `docs/CSV_FORMAT.md` documenting all 14 fields with types and examples. Fix `docs/ARCHITECTURE.md` which incorrectly states "each line is a JSON record." Sanitize `workspace_project_dir` to strip/escape commas before CSV serialization (in both Python and Node.js).
16
+ **Why:** The CSV format is an implicit contract across 5 writer implementations with zero documentation. Commas in directory paths silently corrupt rows.
17
+ **Effort:** S
18
+ **Depends on:** None
19
+ **Status:** Created `docs/CSV_FORMAT.md`, fixed ARCHITECTURE.md JSON→CSV, added comma→underscore guard in Python (`state.py`, `statusline.py`), Node.js (`statusline.js`), and bash (`statusline-full.sh`). Parity test with comma fixture passes. Archived as `openspec/changes/archive/2026-03-12-csv-format-doc-comma-guard/`.
20
+
21
+ ### ~~3. Stderr logging for critical error paths~~ ✅ Done
22
+ **What:** Replace `except OSError: pass` with `sys.stderr.write()` warnings in: `StateFile.append_entry()`, `Config._create_default()`, `Config._read_config()`. Add `UnicodeDecodeError` to config read exception handling. Apply equivalent changes in `statusline.js`.
23
+ **Why:** State write failures cause silent data loss — users see stale dashboards with no indication of why. Statusline output goes to stdout (consumed by Claude Code), so stderr is safe for diagnostics.
24
+ **Effort:** S
25
+ **Depends on:** None
26
+ **Status:** Added `[statusline] warning:` stderr messages to all critical data pipeline error handlers in `config.py`, `state.py`, `statusline.py`, and `statusline.js`. Added `UnicodeDecodeError` to config read exception handling in both Python files. Non-critical handlers (git info, file migration) left silent.
27
+
28
+ ### ~~4. Core data pipeline unit tests~~ ✅ Done
29
+ **What:** Add test files covering: (1) `StateEntry.from_csv_line` ↔ `to_csv_line` round-trip, (2) `calculate_deltas` and `detect_spike`, (3) zone threshold logic in `render_summary`. Cover edge cases: empty data, single entry, negative deltas, boundary percentages (39%/40%/79%/80%).
30
+ **Why:** The primary user-facing feature (`context-stats` CLI) has zero unit tests on its core logic — CSV parsing, statistics, and zone detection are all untested.
31
+ **Effort:** M
32
+ **Depends on:** None
33
+ **Status:** Implemented in `tests/python/test_data_pipeline.py` with 51 tests across 6 classes: TestStateEntryRoundTrip (14), TestStateEntryProperties (3), TestCalculateDeltas (8), TestCalculateStats (6), TestDetectSpike (10), TestZoneThresholds (10). Covers CSV round-trip with old/new formats, comma sanitization, boundary spike detection (exact 15%/3x thresholds), and zone boundaries at 39/40% and 79/80%.
34
+
35
+ ## P2 — Medium Priority
36
+
37
+ ### ~~5. State file cap + rotate~~ ✅ Done
38
+ **What:** After `StateFile.append_entry()`, check line count. If >10,000 lines, truncate to the most recent 5,000. Apply in both Python and Node.js writers.
39
+ **Why:** State files are append-only with no rotation. `read_history()` loads entire files into memory. Heavy users could accumulate 50k+ lines across long sessions.
40
+ **Effort:** S
41
+ **Depends on:** None
42
+ **Status:** Added `_maybe_rotate()` to Python `StateFile` and `maybeRotateStateFile()` to Node.js `statusline.js`. Both use atomic temp-file + rename. Threshold: 10,000 lines, retain: 5,000 lines. Unit tests in `tests/python/test_state_rotation_validation.py` and `tests/node/rotation.test.js`.
43
+
44
+ ### ~~6. Sanitize session_id input~~ ✅ Done
45
+ **What:** Reject session IDs containing `/`, `\`, or `..` at the CLI entry point (`parse_args`) and in `StateFile.__init__()`. Print a clear error message and exit.
46
+ **Why:** Defense-in-depth against path traversal via `context-stats ../../etc/passwd`. Claude Code generates safe UUIDs, but the CLI accepts arbitrary user input.
47
+ **Effort:** XS
48
+ **Depends on:** None
49
+ **Status:** Added `_validate_session_id()` helper in `state.py`, called in `StateFile.__init__()` and `parse_args()` in `context_stats.py`. Rejects `/`, `\`, `..`, and null bytes. Unit tests and CLI subprocess tests in `tests/python/test_state_rotation_validation.py`.
50
+
51
+ ### ~~7. Node.js git command timeout~~ ✅ Done
52
+ **What:** Add `timeout: 5000` to both `execSync` calls in `statusline.js` `getGitInfo()`.
53
+ **Why:** Python's `get_git_info()` has `timeout=5`. Node.js has none — git hangs (network FS, large repo) would block the statusline process indefinitely.
54
+ **Effort:** XS
55
+ **Depends on:** None
56
+ **Status:** Added `timeout: 5000` to both `execSync` calls (`git rev-parse` and `git status`) in `getGitInfo()` in `scripts/statusline.js`.
57
+
58
+ ### ~~8. Repo-level CLAUDE.md~~ ✅ Done
59
+ **What:** Create `CLAUDE.md` at repo root documenting: project purpose, dual-implementation rationale, CSV format contract, test running instructions (`pytest`, `npm test`, `bats`), key architectural decisions, and the 5-script statusline landscape.
60
+ **Why:** Helps AI assistants and new contributors understand the project quickly. Currently the only CLAUDE.md is the user's personal global one.
61
+ **Effort:** S
62
+ **Depends on:** TODO 2 (CSV format doc) for cross-reference
63
+ **Status:** Created `CLAUDE.md` at repo root with all required sections. Cross-references `docs/ARCHITECTURE.md`, `docs/DEVELOPMENT.md`, and `docs/CSV_FORMAT.md`.
64
+
65
+ ## P3 — Low Priority
66
+
67
+ ### ~~9. Add --version flag to context-stats CLI~~ ✅ Done
68
+ **What:** Add `--version` argument to `parse_args()` that prints `cc-context-stats {version}` and exits.
69
+ **Why:** Users can't determine installed version without running the full tool. The footer shows version but only on successful render.
70
+ **Effort:** XS
71
+ **Depends on:** None
72
+ **Status:** Added `--version` / `-V` flag to `parse_args()` in `context_stats.py`. Prints `cc-context-stats {__version__}` and exits. Updated help text and module docstring.
@@ -0,0 +1,101 @@
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
+ ```
13
+ ┌─────────────┐ JSON stdin ┌──────────────────┐
14
+ │ Claude Code │ ──────────────────> │ Statusline Script │
15
+ │ (host) │ <────────────────── │ (sh/py/js) │
16
+ └─────────────┘ stdout text └──────┬───────────┘
17
+ │ writes
18
+
19
+ ┌──────────────────┐
20
+ │ State Files │
21
+ │ ~/.claude/ │
22
+ │ statusline/ │
23
+ └──────┬───────────┘
24
+ │ reads
25
+
26
+ ┌──────────────────┐
27
+ │ Context Stats CLI │
28
+ │ (Python) │
29
+ └──────────────────┘
30
+ ```
31
+
32
+ ## Component Details
33
+
34
+ ### Status Line Scripts
35
+
36
+ Three implementation languages with identical output:
37
+
38
+ | Script | Language | Dependencies |
39
+ | --------------------- | ---------- | ------------ |
40
+ | `statusline-full.sh` | Bash | `jq` |
41
+ | `statusline-git.sh` | Bash | `jq` |
42
+ | `statusline-minimal.sh` | Bash | `jq` |
43
+ | `statusline.py` | Python 3 | None |
44
+ | `statusline.js` | Node.js 18+| None |
45
+
46
+ **Data flow:**
47
+ 1. Claude Code pipes JSON state via stdin on each refresh
48
+ 2. Script parses model info, context tokens, session data
49
+ 3. Script reads `~/.claude/statusline.conf` for user preferences
50
+ 4. Script checks git status for branch/changes info
51
+ 5. Script writes state to `~/.claude/statusline/<session_id>.state`
52
+ 6. Script outputs formatted ANSI text to stdout
53
+
54
+ ### Python Package (`src/claude_statusline/`)
55
+
56
+ The pip-installable package provides both the statusline and context-stats CLI:
57
+
58
+ ```
59
+ src/claude_statusline/
60
+ ├── __init__.py
61
+ ├── __main__.py
62
+ ├── cli/
63
+ │ ├── statusline.py # claude-statusline entry point
64
+ │ └── context_stats.py # context-stats entry point
65
+ ├── core/
66
+ │ ├── colors.py # ANSI color management
67
+ │ ├── config.py # Configuration loading
68
+ │ ├── git.py # Git status detection
69
+ │ └── state.py # State file reading/writing
70
+ ├── formatters/
71
+ │ ├── layout.py # Output width/layout management
72
+ │ ├── time.py # Duration formatting
73
+ │ └── tokens.py # Token count formatting
74
+ ├── graphs/
75
+ │ ├── renderer.py # ASCII graph rendering
76
+ │ └── statistics.py # Data statistics
77
+ └── ui/
78
+ ├── icons.py # Unicode icons
79
+ └── waiting.py # Waiting animation
80
+ ```
81
+
82
+ ### State Files
83
+
84
+ State files persist token history between statusline refreshes:
85
+
86
+ ```
87
+ ~/.claude/statusline/statusline.<session_id>.state
88
+ ```
89
+
90
+ 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.
91
+
92
+ ## Data Privacy
93
+
94
+ All data stays local:
95
+ - State files are written to `~/.claude/statusline/`
96
+ - No network requests are made
97
+ - No telemetry or analytics
98
+
99
+ ## Configuration
100
+
101
+ User preferences are stored in `~/.claude/statusline.conf` as simple `key=value` pairs. See [Configuration](configuration.md) for details.
@@ -0,0 +1,40 @@
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
+
32
+ ## Legacy Format
33
+
34
+ Older state files may contain 2-field lines: `timestamp,total_input_tokens`. The reader defaults all other fields to zero/empty for these lines.
35
+
36
+ ## Example
37
+
38
+ ```
39
+ 1710288000,75000,8500,50000,5000,10000,20000,0.05234,250,45,abc-123-def,claude-opus-4-5,/home/user/my-project,200000
40
+ ```