cc-context-stats 1.3.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.
Files changed (72) hide show
  1. package/.claude/commands/context-stats.md +17 -0
  2. package/.claude/settings.local.json +85 -0
  3. package/.editorconfig +60 -0
  4. package/.eslintrc.json +35 -0
  5. package/.github/dependabot.yml +44 -0
  6. package/.github/workflows/ci.yml +255 -0
  7. package/.github/workflows/release.yml +149 -0
  8. package/.pre-commit-config.yaml +74 -0
  9. package/.prettierrc +33 -0
  10. package/.shellcheckrc +10 -0
  11. package/CHANGELOG.md +100 -0
  12. package/CONTRIBUTING.md +240 -0
  13. package/PUBLISHING_GUIDE.md +69 -0
  14. package/README.md +179 -0
  15. package/config/settings-example.json +7 -0
  16. package/config/settings-node.json +7 -0
  17. package/config/settings-python.json +7 -0
  18. package/docs/configuration.md +83 -0
  19. package/docs/context-stats.md +132 -0
  20. package/docs/installation.md +195 -0
  21. package/docs/scripts.md +116 -0
  22. package/docs/troubleshooting.md +189 -0
  23. package/images/claude-statusline-token-graph.gif +0 -0
  24. package/images/claude-statusline.png +0 -0
  25. package/images/context-status-dumbzone.png +0 -0
  26. package/images/context-status.png +0 -0
  27. package/images/statusline-detail.png +0 -0
  28. package/images/token-graph.jpeg +0 -0
  29. package/images/token-graph.png +0 -0
  30. package/install +344 -0
  31. package/install.sh +272 -0
  32. package/jest.config.js +11 -0
  33. package/npm-publish.sh +33 -0
  34. package/package.json +36 -0
  35. package/publish.sh +24 -0
  36. package/pyproject.toml +113 -0
  37. package/requirements-dev.txt +12 -0
  38. package/scripts/context-stats.sh +970 -0
  39. package/scripts/statusline-full.sh +241 -0
  40. package/scripts/statusline-git.sh +32 -0
  41. package/scripts/statusline-minimal.sh +11 -0
  42. package/scripts/statusline.js +350 -0
  43. package/scripts/statusline.py +312 -0
  44. package/show_raw_claude_code_api.js +11 -0
  45. package/src/claude_statusline/__init__.py +11 -0
  46. package/src/claude_statusline/__main__.py +6 -0
  47. package/src/claude_statusline/cli/__init__.py +1 -0
  48. package/src/claude_statusline/cli/context_stats.py +379 -0
  49. package/src/claude_statusline/cli/statusline.py +172 -0
  50. package/src/claude_statusline/core/__init__.py +1 -0
  51. package/src/claude_statusline/core/colors.py +55 -0
  52. package/src/claude_statusline/core/config.py +98 -0
  53. package/src/claude_statusline/core/git.py +67 -0
  54. package/src/claude_statusline/core/state.py +266 -0
  55. package/src/claude_statusline/formatters/__init__.py +1 -0
  56. package/src/claude_statusline/formatters/time.py +50 -0
  57. package/src/claude_statusline/formatters/tokens.py +70 -0
  58. package/src/claude_statusline/graphs/__init__.py +1 -0
  59. package/src/claude_statusline/graphs/renderer.py +346 -0
  60. package/src/claude_statusline/graphs/statistics.py +58 -0
  61. package/tests/bash/test_install.bats +29 -0
  62. package/tests/bash/test_statusline_full.bats +109 -0
  63. package/tests/bash/test_statusline_git.bats +42 -0
  64. package/tests/bash/test_statusline_minimal.bats +37 -0
  65. package/tests/fixtures/json/high_usage.json +17 -0
  66. package/tests/fixtures/json/low_usage.json +17 -0
  67. package/tests/fixtures/json/medium_usage.json +17 -0
  68. package/tests/fixtures/json/valid_full.json +30 -0
  69. package/tests/fixtures/json/valid_minimal.json +9 -0
  70. package/tests/node/statusline.test.js +199 -0
  71. package/tests/python/conftest.py +84 -0
  72. package/tests/python/test_statusline.py +154 -0
@@ -0,0 +1,189 @@
1
+ # Troubleshooting
2
+
3
+ ## Common Issues
4
+
5
+ ### Status line not appearing
6
+
7
+ **macOS/Linux:**
8
+
9
+ 1. Check script is executable:
10
+
11
+ ```bash
12
+ chmod +x ~/.claude/statusline.sh
13
+ ```
14
+
15
+ 2. Test the script:
16
+
17
+ ```bash
18
+ echo '{"model":{"display_name":"Test"}}' | ~/.claude/statusline.sh
19
+ ```
20
+
21
+ 3. Verify settings.json configuration:
22
+
23
+ ```bash
24
+ cat ~/.claude/settings.json
25
+ ```
26
+
27
+ **Windows (Python):**
28
+
29
+ ```powershell
30
+ echo {"model":{"display_name":"Test"}} | python %USERPROFILE%\.claude\statusline.py
31
+ ```
32
+
33
+ ### jq not found
34
+
35
+ The bash scripts require `jq` for JSON parsing.
36
+
37
+ **macOS:**
38
+
39
+ ```bash
40
+ brew install jq
41
+ ```
42
+
43
+ **Linux (Debian/Ubuntu):**
44
+
45
+ ```bash
46
+ sudo apt install jq
47
+ ```
48
+
49
+ **Linux (Fedora/RHEL):**
50
+
51
+ ```bash
52
+ sudo dnf install jq
53
+ ```
54
+
55
+ Alternatively, use the Python or Node.js version which don't require `jq`.
56
+
57
+ ### context-stats command not found
58
+
59
+ 1. Verify installation:
60
+
61
+ ```bash
62
+ ls -la ~/.local/bin/context-stats
63
+ ```
64
+
65
+ 2. Check PATH:
66
+
67
+ ```bash
68
+ echo $PATH | grep -q "$HOME/.local/bin" && echo "In PATH" || echo "Not in PATH"
69
+ ```
70
+
71
+ 3. Add to PATH if needed:
72
+
73
+ ```bash
74
+ # zsh
75
+ echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc
76
+ source ~/.zshrc
77
+
78
+ # bash
79
+ echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
80
+ source ~/.bashrc
81
+ ```
82
+
83
+ ### No token graph data
84
+
85
+ Token history requires:
86
+
87
+ 1. `show_delta=true` in `~/.claude/statusline.conf` (default)
88
+ 2. Active Claude Code session generating state files
89
+ 3. State files at `~/.claude/statusline/statusline.<session_id>.state`
90
+
91
+ Check for state files:
92
+
93
+ ```bash
94
+ ls -la ~/.claude/statusline/statusline.*.state
95
+ ```
96
+
97
+ ### Git info not showing
98
+
99
+ 1. Verify you're in a git repository:
100
+
101
+ ```bash
102
+ git rev-parse --is-inside-work-tree
103
+ ```
104
+
105
+ 2. Check git is installed:
106
+
107
+ ```bash
108
+ which git
109
+ ```
110
+
111
+ ### Wrong token colors
112
+
113
+ Token colors depend on availability percentage:
114
+
115
+ | Availability | Expected Color |
116
+ | ------------ | -------------- |
117
+ | > 50% | Green |
118
+ | > 25% | Yellow |
119
+ | <= 25% | Red |
120
+
121
+ If colors look wrong, check terminal color support.
122
+
123
+ ### Delta always shows zero
124
+
125
+ Token delta requires multiple statusline refreshes. The first refresh establishes a baseline; subsequent refreshes show the delta.
126
+
127
+ ### Configuration not taking effect
128
+
129
+ 1. Check config file location:
130
+
131
+ ```bash
132
+ cat ~/.claude/statusline.conf
133
+ ```
134
+
135
+ 2. Verify syntax (no spaces around `=`):
136
+
137
+ ```bash
138
+ # Correct
139
+ show_delta=true
140
+
141
+ # Wrong
142
+ show_delta = true
143
+ ```
144
+
145
+ 3. Restart Claude Code after config changes.
146
+
147
+ ## Debug Mode
148
+
149
+ ### Test script output
150
+
151
+ ```bash
152
+ # Create test input
153
+ cat << 'EOF' > /tmp/test-input.json
154
+ {
155
+ "model": {"display_name": "Opus 4.5"},
156
+ "cwd": "/test/project",
157
+ "session_id": "test123",
158
+ "context": {
159
+ "tokens_remaining": 64000,
160
+ "context_window": 200000,
161
+ "autocompact_buffer_tokens": 45000
162
+ }
163
+ }
164
+ EOF
165
+
166
+ # Test each script
167
+ cat /tmp/test-input.json | ~/.claude/statusline.sh
168
+ cat /tmp/test-input.json | python3 ~/.claude/statusline.py
169
+ cat /tmp/test-input.json | node ~/.claude/statusline.js
170
+ ```
171
+
172
+ ### Check state files
173
+
174
+ ```bash
175
+ # View state file content
176
+ cat ~/.claude/statusline/statusline.*.state
177
+
178
+ # Watch state file updates
179
+ watch -n 1 'tail -5 ~/.claude/statusline/statusline.*.state'
180
+ ```
181
+
182
+ ## Getting Help
183
+
184
+ - Check [existing issues](https://github.com/luongnv89/cc-context-stats/issues)
185
+ - Open a new issue with:
186
+ - Operating system
187
+ - Shell type (bash/zsh)
188
+ - Script version being used
189
+ - Error messages or unexpected behavior
Binary file
Binary file
Binary file
Binary file
Binary file
package/install ADDED
@@ -0,0 +1,344 @@
1
+ #!/bin/bash
2
+ #
3
+ # Claude Code Status Line Installer
4
+ # Installs and configures a status line for Claude Code
5
+ #
6
+ # Usage:
7
+ # Local: ./install.sh
8
+ # Remote: curl -fsSL https://raw.githubusercontent.com/luongnv89/claude-statusline/main/install.sh | bash
9
+ #
10
+
11
+ set -e
12
+
13
+ # Colors for output
14
+ RED='\033[0;31m'
15
+ GREEN='\033[0;32m'
16
+ YELLOW='\033[0;33m'
17
+ BLUE='\033[0;34m'
18
+ RESET='\033[0m'
19
+
20
+ CLAUDE_DIR="$HOME/.claude"
21
+ SETTINGS_FILE="$CLAUDE_DIR/settings.json"
22
+ LOCAL_BIN="$HOME/.local/bin"
23
+
24
+ # GitHub repository info for remote installation
25
+ GITHUB_RAW_URL="https://raw.githubusercontent.com/luongnv89/claude-statusline/main"
26
+ GITHUB_API_URL="https://api.github.com/repos/luongnv89/claude-statusline"
27
+
28
+ # Detect if running from pipe (curl) or locally
29
+ detect_install_mode() {
30
+ # Check if we have a valid script file with scripts directory
31
+ if [ -n "${BASH_SOURCE[0]}" ] && [ -f "${BASH_SOURCE[0]}" ]; then
32
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
33
+ if [ -d "$SCRIPT_DIR/scripts" ]; then
34
+ INSTALL_MODE="local"
35
+ INTERACTIVE=true
36
+ [ -t 0 ] || INTERACTIVE=false
37
+ return
38
+ fi
39
+ fi
40
+ # Running from curl/pipe or script directory not found
41
+ INSTALL_MODE="remote"
42
+ INTERACTIVE=false
43
+ }
44
+
45
+ echo -e "${BLUE}Claude Code Status Line Installer${RESET}"
46
+ echo "=================================="
47
+ echo
48
+
49
+ detect_install_mode
50
+
51
+ if [ "$INSTALL_MODE" = "remote" ]; then
52
+ echo -e "${YELLOW}Remote installation mode${RESET}"
53
+ echo "Downloading from GitHub..."
54
+ echo
55
+ else
56
+ echo -e "${GREEN}Local installation mode${RESET}"
57
+ echo
58
+ fi
59
+
60
+ # Check for curl (required for remote installation)
61
+ check_curl() {
62
+ if [ "$INSTALL_MODE" = "remote" ]; then
63
+ if ! command -v curl &>/dev/null; then
64
+ echo -e "${RED}Error: 'curl' is required for remote installation${RESET}"
65
+ exit 1
66
+ fi
67
+ fi
68
+ }
69
+
70
+ # Check for jq (required for bash scripts)
71
+ check_jq() {
72
+ if ! command -v jq &>/dev/null; then
73
+ echo -e "${YELLOW}Warning: 'jq' is not installed.${RESET}"
74
+ echo "jq is required for bash status line scripts."
75
+ echo
76
+ if [[ "$OSTYPE" == "darwin"* ]]; then
77
+ echo "Install with: brew install jq"
78
+ else
79
+ echo "Install with: sudo apt install jq (Debian/Ubuntu)"
80
+ echo " or: sudo yum install jq (RHEL/CentOS)"
81
+ fi
82
+ echo
83
+ if [ "$INTERACTIVE" = true ]; then
84
+ read -p "Continue anyway? (y/n) " -n 1 -r
85
+ echo
86
+ if [[ ! $REPLY =~ ^[Yy]$ ]]; then
87
+ exit 1
88
+ fi
89
+ fi
90
+ else
91
+ echo -e "${GREEN}✓${RESET} jq is installed"
92
+ fi
93
+ }
94
+
95
+ # Download a file from GitHub
96
+ download_file() {
97
+ local remote_path="$1"
98
+ local dest_path="$2"
99
+ local url="$GITHUB_RAW_URL/$remote_path"
100
+
101
+ if curl -fsSL "$url" -o "$dest_path"; then
102
+ chmod +x "$dest_path"
103
+ return 0
104
+ else
105
+ echo -e "${RED}Error: Failed to download $remote_path${RESET}"
106
+ return 1
107
+ fi
108
+ }
109
+
110
+ # Get latest commit hash from GitHub
111
+ get_remote_commit_hash() {
112
+ local hash
113
+ hash=$(curl -fsSL "$GITHUB_API_URL/commits/main" 2>/dev/null | grep -m1 '"sha"' | cut -d'"' -f4 | head -c7)
114
+ echo "${hash:-unknown}"
115
+ }
116
+
117
+ # Select script type
118
+ select_script() {
119
+ echo
120
+ echo "Available status line scripts:"
121
+ echo " 1) minimal - Simple: model + directory"
122
+ echo " 2) git - With git branch info"
123
+ echo " 3) full - Full featured with context usage (recommended)"
124
+ echo " 4) python - Python version (full featured)"
125
+ echo " 5) node - Node.js version (full featured)"
126
+ echo
127
+
128
+ if [ "$INTERACTIVE" = true ]; then
129
+ read -rp "Select script [1-5, default: 3]: " choice
130
+ else
131
+ echo "Non-interactive mode detected. Using default: full (3)"
132
+ choice=3
133
+ fi
134
+
135
+ case ${choice:-3} in
136
+ 1)
137
+ SCRIPT_REMOTE="scripts/statusline-minimal.sh"
138
+ SCRIPT_NAME="statusline.sh"
139
+ ;;
140
+ 2)
141
+ SCRIPT_REMOTE="scripts/statusline-git.sh"
142
+ SCRIPT_NAME="statusline.sh"
143
+ ;;
144
+ 3)
145
+ SCRIPT_REMOTE="scripts/statusline-full.sh"
146
+ SCRIPT_NAME="statusline.sh"
147
+ ;;
148
+ 4)
149
+ SCRIPT_REMOTE="scripts/statusline.py"
150
+ SCRIPT_NAME="statusline.py"
151
+ ;;
152
+ 5)
153
+ SCRIPT_REMOTE="scripts/statusline.js"
154
+ SCRIPT_NAME="statusline.js"
155
+ ;;
156
+ *)
157
+ echo -e "${RED}Invalid choice${RESET}"
158
+ exit 1
159
+ ;;
160
+ esac
161
+
162
+ if [ "$INSTALL_MODE" = "local" ]; then
163
+ SCRIPT_SRC="$SCRIPT_DIR/$SCRIPT_REMOTE"
164
+ fi
165
+ }
166
+
167
+ # Create .claude directory if needed
168
+ ensure_claude_dir() {
169
+ if [ ! -d "$CLAUDE_DIR" ]; then
170
+ echo -e "${YELLOW}Creating $CLAUDE_DIR directory...${RESET}"
171
+ mkdir -p "$CLAUDE_DIR"
172
+ fi
173
+ echo -e "${GREEN}✓${RESET} Claude directory exists: $CLAUDE_DIR"
174
+ }
175
+
176
+ # Install/copy script
177
+ install_script() {
178
+ DEST="$CLAUDE_DIR/$SCRIPT_NAME"
179
+
180
+ if [ -f "$DEST" ]; then
181
+ echo
182
+ echo -e "${YELLOW}Warning: $DEST already exists${RESET}"
183
+ if [ "$INTERACTIVE" = true ]; then
184
+ read -p "Overwrite? (y/n) " -n 1 -r
185
+ echo
186
+ if [[ ! $REPLY =~ ^[Yy]$ ]]; then
187
+ echo "Keeping existing script."
188
+ return
189
+ fi
190
+ else
191
+ echo "Overwriting in non-interactive mode..."
192
+ fi
193
+ fi
194
+
195
+ if [ "$INSTALL_MODE" = "local" ]; then
196
+ cp "$SCRIPT_SRC" "$DEST"
197
+ chmod +x "$DEST"
198
+ else
199
+ download_file "$SCRIPT_REMOTE" "$DEST"
200
+ fi
201
+ echo -e "${GREEN}✓${RESET} Installed: $DEST"
202
+ }
203
+
204
+ # Install token-graph CLI tool
205
+ install_token_graph() {
206
+ echo
207
+
208
+ # Create ~/.local/bin if it doesn't exist
209
+ if [ ! -d "$LOCAL_BIN" ]; then
210
+ echo -e "${YELLOW}Creating $LOCAL_BIN directory...${RESET}"
211
+ mkdir -p "$LOCAL_BIN"
212
+ fi
213
+
214
+ DEST="$LOCAL_BIN/token-graph"
215
+
216
+ if [ -f "$DEST" ]; then
217
+ echo -e "${YELLOW}Warning: $DEST already exists${RESET}"
218
+ if [ "$INTERACTIVE" = true ]; then
219
+ read -p "Overwrite? (y/n) " -n 1 -r
220
+ echo
221
+ if [[ ! $REPLY =~ ^[Yy]$ ]]; then
222
+ echo "Keeping existing token-graph."
223
+ return
224
+ fi
225
+ else
226
+ echo "Overwriting in non-interactive mode..."
227
+ fi
228
+ fi
229
+
230
+ # Get commit hash for version embedding
231
+ local commit_hash
232
+ if [ "$INSTALL_MODE" = "local" ]; then
233
+ commit_hash=$(git -C "$SCRIPT_DIR" rev-parse --short HEAD 2>/dev/null || echo "unknown")
234
+ cp "$SCRIPT_DIR/scripts/token-graph.sh" "$DEST"
235
+ else
236
+ commit_hash=$(get_remote_commit_hash)
237
+ download_file "scripts/token-graph.sh" "$DEST"
238
+ fi
239
+
240
+ # Embed commit hash
241
+ sed -i.bak "s/COMMIT_HASH=\"dev\"/COMMIT_HASH=\"$commit_hash\"/" "$DEST" && rm -f "$DEST.bak"
242
+ chmod +x "$DEST"
243
+ echo -e "${GREEN}✓${RESET} Installed: $DEST (v1.0.0-$commit_hash)"
244
+
245
+ # Check if ~/.local/bin is in PATH
246
+ if [[ ":$PATH:" != *":$LOCAL_BIN:"* ]]; then
247
+ echo
248
+ echo -e "${YELLOW}Note: $LOCAL_BIN is not in your PATH${RESET}"
249
+ echo "Add it to your shell configuration:"
250
+ echo
251
+ if [[ "$SHELL" == *"zsh"* ]]; then
252
+ echo " echo 'export PATH=\"\$HOME/.local/bin:\$PATH\"' >> ~/.zshrc"
253
+ echo " source ~/.zshrc"
254
+ else
255
+ echo " echo 'export PATH=\"\$HOME/.local/bin:\$PATH\"' >> ~/.bashrc"
256
+ echo " source ~/.bashrc"
257
+ fi
258
+ fi
259
+ }
260
+
261
+ # Create config file with defaults if it doesn't exist
262
+ create_config() {
263
+ CONFIG_FILE="$CLAUDE_DIR/statusline.conf"
264
+
265
+ if [ -f "$CONFIG_FILE" ]; then
266
+ echo -e "${GREEN}✓${RESET} Config file exists: $CONFIG_FILE"
267
+ return
268
+ fi
269
+
270
+ cat >"$CONFIG_FILE" <<'EOF'
271
+ # Autocompact setting - sync with Claude Code's /config
272
+ autocompact=true
273
+
274
+ # Token display format
275
+ token_detail=true
276
+
277
+ # Show token delta since last refresh (adds file I/O on every refresh)
278
+ # Disable if you don't need it to reduce overhead
279
+ show_delta=true
280
+
281
+ # Show session_id in status line
282
+ show_session=true
283
+ EOF
284
+ echo -e "${GREEN}✓${RESET} Created config file: $CONFIG_FILE"
285
+ }
286
+
287
+ # Update settings.json
288
+ update_settings() {
289
+ echo
290
+
291
+ # Create settings file if it doesn't exist
292
+ if [ ! -f "$SETTINGS_FILE" ]; then
293
+ echo '{}' >"$SETTINGS_FILE"
294
+ echo -e "${GREEN}✓${RESET} Created $SETTINGS_FILE"
295
+ fi
296
+
297
+ # Check if jq is available for JSON manipulation
298
+ if command -v jq &>/dev/null; then
299
+ # Backup existing settings
300
+ cp "$SETTINGS_FILE" "$SETTINGS_FILE.backup"
301
+
302
+ # Add/update statusLine configuration
303
+ SCRIPT_PATH="$HOME/.claude/$SCRIPT_NAME"
304
+ jq --arg cmd "$SCRIPT_PATH" '.statusLine = {"type": "command", "command": $cmd}' \
305
+ "$SETTINGS_FILE.backup" >"$SETTINGS_FILE"
306
+
307
+ rm "$SETTINGS_FILE.backup"
308
+ echo -e "${GREEN}✓${RESET} Updated settings.json with statusLine configuration"
309
+ else
310
+ echo -e "${YELLOW}Note: Could not update settings.json (jq not installed)${RESET}"
311
+ echo
312
+ echo "Please add this to $SETTINGS_FILE manually:"
313
+ echo
314
+ echo ' "statusLine": {'
315
+ echo ' "type": "command",'
316
+ echo " \"command\": \"~/.claude/$SCRIPT_NAME\""
317
+ echo ' }'
318
+ fi
319
+ }
320
+
321
+ # Main installation
322
+ main() {
323
+ check_curl
324
+ check_jq
325
+ ensure_claude_dir
326
+ select_script
327
+ install_script
328
+ install_token_graph
329
+ create_config
330
+ update_settings
331
+
332
+ echo
333
+ echo -e "${GREEN}Installation complete!${RESET}"
334
+ echo
335
+ echo "Your status line is now configured."
336
+ echo "Restart Claude Code to see the changes."
337
+ echo
338
+ echo "To customize, edit: $CLAUDE_DIR/$SCRIPT_NAME"
339
+ echo "To change settings, edit: $CLAUDE_DIR/statusline.conf"
340
+ echo
341
+ echo "Run 'token-graph' to visualize token usage for any session."
342
+ }
343
+
344
+ main