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.
- package/.github/ISSUE_TEMPLATE/bug_report.md +49 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +31 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +33 -0
- package/.github/workflows/ci.yml +39 -2
- package/CHANGELOG.md +16 -8
- package/CLAUDE.md +54 -0
- package/CODE_OF_CONDUCT.md +59 -0
- package/LICENSE +21 -0
- package/README.md +9 -0
- package/RELEASE_NOTES.md +16 -7
- package/SECURITY.md +44 -0
- package/TODOS.md +72 -0
- package/docs/ARCHITECTURE.md +101 -0
- package/docs/CSV_FORMAT.md +40 -0
- package/docs/DEPLOYMENT.md +60 -0
- package/docs/DEVELOPMENT.md +125 -0
- package/package.json +2 -2
- package/pyproject.toml +1 -1
- package/scripts/statusline-full.sh +1 -1
- package/scripts/statusline.js +61 -8
- package/scripts/statusline.py +9 -8
- package/src/claude_statusline/__init__.py +1 -1
- package/src/claude_statusline/cli/context_stats.py +20 -1
- package/src/claude_statusline/core/config.py +5 -4
- package/src/claude_statusline/core/state.py +64 -7
- package/tests/bash/test_parity.bats +315 -0
- package/tests/fixtures/json/comma_in_path.json +31 -0
- package/tests/node/rotation.test.js +89 -0
- package/tests/python/test_data_pipeline.py +446 -0
- package/tests/python/test_state_rotation_validation.py +232 -0
- package/.claude/commands/context-stats.md +0 -17
- package/.claude/settings.local.json +0 -120
|
@@ -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.
|
package/.github/workflows/ci.yml
CHANGED
|
@@ -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" ]]
|
|
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
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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.
|
|
1
|
+
## v1.6.0 — 2026-03-13
|
|
2
2
|
|
|
3
|
-
###
|
|
4
|
-
- **
|
|
5
|
-
- **
|
|
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
|
-
###
|
|
8
|
-
-
|
|
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.
|
|
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
|
+
```
|