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.
- package/.claude/commands/context-stats.md +17 -0
- package/.claude/settings.local.json +85 -0
- package/.editorconfig +60 -0
- package/.eslintrc.json +35 -0
- package/.github/dependabot.yml +44 -0
- package/.github/workflows/ci.yml +255 -0
- package/.github/workflows/release.yml +149 -0
- package/.pre-commit-config.yaml +74 -0
- package/.prettierrc +33 -0
- package/.shellcheckrc +10 -0
- package/CHANGELOG.md +100 -0
- package/CONTRIBUTING.md +240 -0
- package/PUBLISHING_GUIDE.md +69 -0
- package/README.md +179 -0
- package/config/settings-example.json +7 -0
- package/config/settings-node.json +7 -0
- package/config/settings-python.json +7 -0
- package/docs/configuration.md +83 -0
- package/docs/context-stats.md +132 -0
- package/docs/installation.md +195 -0
- package/docs/scripts.md +116 -0
- package/docs/troubleshooting.md +189 -0
- package/images/claude-statusline-token-graph.gif +0 -0
- package/images/claude-statusline.png +0 -0
- package/images/context-status-dumbzone.png +0 -0
- package/images/context-status.png +0 -0
- package/images/statusline-detail.png +0 -0
- package/images/token-graph.jpeg +0 -0
- package/images/token-graph.png +0 -0
- package/install +344 -0
- package/install.sh +272 -0
- package/jest.config.js +11 -0
- package/npm-publish.sh +33 -0
- package/package.json +36 -0
- package/publish.sh +24 -0
- package/pyproject.toml +113 -0
- package/requirements-dev.txt +12 -0
- package/scripts/context-stats.sh +970 -0
- package/scripts/statusline-full.sh +241 -0
- package/scripts/statusline-git.sh +32 -0
- package/scripts/statusline-minimal.sh +11 -0
- package/scripts/statusline.js +350 -0
- package/scripts/statusline.py +312 -0
- package/show_raw_claude_code_api.js +11 -0
- package/src/claude_statusline/__init__.py +11 -0
- package/src/claude_statusline/__main__.py +6 -0
- package/src/claude_statusline/cli/__init__.py +1 -0
- package/src/claude_statusline/cli/context_stats.py +379 -0
- package/src/claude_statusline/cli/statusline.py +172 -0
- package/src/claude_statusline/core/__init__.py +1 -0
- package/src/claude_statusline/core/colors.py +55 -0
- package/src/claude_statusline/core/config.py +98 -0
- package/src/claude_statusline/core/git.py +67 -0
- package/src/claude_statusline/core/state.py +266 -0
- package/src/claude_statusline/formatters/__init__.py +1 -0
- package/src/claude_statusline/formatters/time.py +50 -0
- package/src/claude_statusline/formatters/tokens.py +70 -0
- package/src/claude_statusline/graphs/__init__.py +1 -0
- package/src/claude_statusline/graphs/renderer.py +346 -0
- package/src/claude_statusline/graphs/statistics.py +58 -0
- package/tests/bash/test_install.bats +29 -0
- package/tests/bash/test_statusline_full.bats +109 -0
- package/tests/bash/test_statusline_git.bats +42 -0
- package/tests/bash/test_statusline_minimal.bats +37 -0
- package/tests/fixtures/json/high_usage.json +17 -0
- package/tests/fixtures/json/low_usage.json +17 -0
- package/tests/fixtures/json/medium_usage.json +17 -0
- package/tests/fixtures/json/valid_full.json +30 -0
- package/tests/fixtures/json/valid_minimal.json +9 -0
- package/tests/node/statusline.test.js +199 -0
- package/tests/python/conftest.py +84 -0
- package/tests/python/test_statusline.py +154 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Display ASCII graph of token usage for current session
|
|
3
|
+
argument-hint: [session_id] [--type cumulative|delta|both] [--no-color]
|
|
4
|
+
allowed-tools: Bash(*)
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Context Stats
|
|
8
|
+
|
|
9
|
+
Display the token consumption history as ASCII graphs.
|
|
10
|
+
|
|
11
|
+
**IMPORTANT**: This command executes a bash script and displays its output directly. Do NOT analyze or interpret the results - simply show them to the user.
|
|
12
|
+
|
|
13
|
+
Execute the token graph script:
|
|
14
|
+
|
|
15
|
+
!`bash /Users/montimage/buildspace/luongnv89/claude-statusline/scripts/context-stats.sh $ARGUMENTS`
|
|
16
|
+
|
|
17
|
+
The output above shows the token usage visualization. No further analysis is needed.
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Bash(/Users/montimage/buildspace/luongnv89/claude-statusline/scripts/statusline-full.sh:*)",
|
|
5
|
+
"Bash(find:*)",
|
|
6
|
+
"Bash(GIT_DIR=/Users/montimage/buildspace/luongnv89/claude-statusline/.git git add scripts/)",
|
|
7
|
+
"Bash(GIT_DIR=/Users/montimage/buildspace/luongnv89/claude-statusline/.git git -c core.hooksPath=/dev/null commit:*)",
|
|
8
|
+
"Bash(GIT_SSH_COMMAND=\"ssh -F /dev/null -o IdentityFile=~/.ssh/id_ed25519\" git push origin main)",
|
|
9
|
+
"Bash(/Users/montimage/buildspace/luongnv89/claude-statusline/scripts/statusline-original.sh)",
|
|
10
|
+
"Bash(/Users/montimage/buildspace/luongnv89/claude-statusline/scripts/statusline-git.sh)",
|
|
11
|
+
"Bash(/Users/montimage/buildspace/luongnv89/claude-statusline/scripts/statusline-minimal.sh:*)",
|
|
12
|
+
"Bash(ls:*)",
|
|
13
|
+
"Bash(wc:*)",
|
|
14
|
+
"Bash(pytest:*)",
|
|
15
|
+
"Bash(bats:*)",
|
|
16
|
+
"Bash(ruff check:*)",
|
|
17
|
+
"Bash(npx eslint:*)",
|
|
18
|
+
"Bash(shellcheck:*)",
|
|
19
|
+
"Bash(gh run list:*)",
|
|
20
|
+
"Bash(gh run view:*)",
|
|
21
|
+
"Bash(ruff format:*)",
|
|
22
|
+
"Bash(git rm:*)",
|
|
23
|
+
"Bash(scripts/statusline-full.sh:*)",
|
|
24
|
+
"Bash(./scripts/statusline-full.sh:*)",
|
|
25
|
+
"Bash(~/.claude/statusline.conf)",
|
|
26
|
+
"Bash(/Users/montimage/buildspace/luongnv89/claude-statusline/scripts/context-stats.sh:*)",
|
|
27
|
+
"Bash(bash -x:*)",
|
|
28
|
+
"Bash(timeout 5 bash:*)",
|
|
29
|
+
"Bash(perl -e 'alarm 10; exec @ARGV' -- /Users/montimage/buildspace/luongnv89/claude-statusline/scripts/context-stats.sh test-session --no-color)",
|
|
30
|
+
"Bash(bash -c '/Users/montimage/buildspace/luongnv89/claude-statusline/scripts/context-stats.sh test-session --no-color; echo \"\"Exit code: $?\"\"')",
|
|
31
|
+
"Bash(/bin/bash /Users/montimage/buildspace/luongnv89/claude-statusline/scripts/context-stats.sh:*)",
|
|
32
|
+
"Bash(/bin/bash:*)",
|
|
33
|
+
"Bash(/opt/homebrew/bin/bash:*)",
|
|
34
|
+
"Bash(COLUMNS=80 LINES=40 /bin/bash:*)",
|
|
35
|
+
"Bash(pre-commit:*)",
|
|
36
|
+
"Bash(./install.sh)",
|
|
37
|
+
"Bash(context-stats:*)",
|
|
38
|
+
"Bash(gh pr list:*)",
|
|
39
|
+
"Bash(apt-get update:*)",
|
|
40
|
+
"Bash(apt-get install:*)",
|
|
41
|
+
"Bash(pip install:*)",
|
|
42
|
+
"Bash(mypy:*)",
|
|
43
|
+
"Bash(npm ci:*)",
|
|
44
|
+
"Bash(npx prettier --check scripts/statusline.js)",
|
|
45
|
+
"Bash(cat:*)",
|
|
46
|
+
"Bash(node -c:*)",
|
|
47
|
+
"Bash(xxd:*)",
|
|
48
|
+
"Bash(node --version:*)",
|
|
49
|
+
"Bash(awk:*)",
|
|
50
|
+
"Bash(grep:*)",
|
|
51
|
+
"Bash(npm test:*)",
|
|
52
|
+
"Bash(SAMPLE_INPUT='{\"\"\"\"model\"\"\"\":{\"\"\"\"display_name\"\"\"\":\"\"\"\"Claude 3.5 Sonnet\"\"\"\"},\"\"\"\"workspace\"\"\"\":{\"\"\"\"current_dir\"\"\"\":\"\"\"\"/tmp/test\"\"\"\",\"\"\"\"project_dir\"\"\"\":\"\"\"\"/tmp/test\"\"\"\"},\"\"\"\"context_window\"\"\"\":{\"\"\"\"context_window_size\"\"\"\":200000,\"\"\"\"current_usage\"\"\"\":{\"\"\"\"input_tokens\"\"\"\":1000,\"\"\"\"cache_creation_input_tokens\"\"\"\":500,\"\"\"\"cache_read_input_tokens\"\"\"\":200}}}')",
|
|
53
|
+
"Bash(echo \"Testing bash scripts...\" echo \"$SAMPLE_INPUT\")",
|
|
54
|
+
"Bash(./scripts/statusline-git.sh echo \"$SAMPLE_INPUT\")",
|
|
55
|
+
"Bash(./scripts/statusline-minimal.sh:*)",
|
|
56
|
+
"Bash(echo \"Testing Python script...\" echo \"$SAMPLE_INPUT\")",
|
|
57
|
+
"Bash(python3:*)",
|
|
58
|
+
"Bash(echo \"Testing Node.js script...\" echo \"$SAMPLE_INPUT\")",
|
|
59
|
+
"Bash(node ./scripts/statusline.js:*)",
|
|
60
|
+
"Bash(./scripts/statusline-git.sh echo \"\" echo \"$SAMPLE_INPUT\")",
|
|
61
|
+
"Bash(export PATH=\"$HOME/.local/bin:$PATH\")",
|
|
62
|
+
"Bash(~/.local/bin/context-stats test-session:*)",
|
|
63
|
+
"Bash(~/.local/bin/context-stats)",
|
|
64
|
+
"Bash(~/.local/bin/context-stats:*)",
|
|
65
|
+
"Bash(gh run watch:*)",
|
|
66
|
+
"Bash(claude-statusline)",
|
|
67
|
+
"Bash(python -m build:*)",
|
|
68
|
+
"Bash(unzip:*)",
|
|
69
|
+
"Bash(twine:*)",
|
|
70
|
+
"WebFetch(domain:pypi.org)",
|
|
71
|
+
"Bash(python -m pytest:*)",
|
|
72
|
+
"Bash(python:*)",
|
|
73
|
+
"Bash(python -c:*)",
|
|
74
|
+
"Bash(timeout 5 context-stats:*)",
|
|
75
|
+
"Bash(gtimeout 5 context-stats:*)",
|
|
76
|
+
"Bash(./scripts/context-stats.sh:*)",
|
|
77
|
+
"Bash(echo:*)",
|
|
78
|
+
"Bash(CLAUDE_SESSION_ID=\"bf8a8370-18d6-473d-8f12-51e7f3c2a9d0\" node scripts/statusline.js:*)",
|
|
79
|
+
"Skill(pre-commit)",
|
|
80
|
+
"Bash(npm run format:check:*)",
|
|
81
|
+
"Bash(bash:*)",
|
|
82
|
+
"Bash(git tag:*)"
|
|
83
|
+
]
|
|
84
|
+
}
|
|
85
|
+
}
|
package/.editorconfig
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# EditorConfig for claude-statusline project
|
|
2
|
+
# https://editorconfig.org
|
|
3
|
+
|
|
4
|
+
root = true
|
|
5
|
+
|
|
6
|
+
# Default settings for all files
|
|
7
|
+
[*]
|
|
8
|
+
charset = utf-8
|
|
9
|
+
end_of_line = lf
|
|
10
|
+
insert_final_newline = true
|
|
11
|
+
trim_trailing_whitespace = true
|
|
12
|
+
indent_style = space
|
|
13
|
+
indent_size = 4
|
|
14
|
+
|
|
15
|
+
# Shell scripts
|
|
16
|
+
[*.{sh,bash}]
|
|
17
|
+
indent_style = space
|
|
18
|
+
indent_size = 4
|
|
19
|
+
|
|
20
|
+
# Python
|
|
21
|
+
[*.py]
|
|
22
|
+
indent_style = space
|
|
23
|
+
indent_size = 4
|
|
24
|
+
max_line_length = 100
|
|
25
|
+
|
|
26
|
+
# JavaScript
|
|
27
|
+
[*.js]
|
|
28
|
+
indent_style = space
|
|
29
|
+
indent_size = 4
|
|
30
|
+
max_line_length = 100
|
|
31
|
+
|
|
32
|
+
# JSON files
|
|
33
|
+
[*.json]
|
|
34
|
+
indent_style = space
|
|
35
|
+
indent_size = 2
|
|
36
|
+
|
|
37
|
+
# YAML files
|
|
38
|
+
[*.{yml,yaml}]
|
|
39
|
+
indent_style = space
|
|
40
|
+
indent_size = 2
|
|
41
|
+
|
|
42
|
+
# TOML files
|
|
43
|
+
[*.toml]
|
|
44
|
+
indent_style = space
|
|
45
|
+
indent_size = 4
|
|
46
|
+
|
|
47
|
+
# Markdown
|
|
48
|
+
[*.md]
|
|
49
|
+
indent_style = space
|
|
50
|
+
indent_size = 2
|
|
51
|
+
trim_trailing_whitespace = false
|
|
52
|
+
|
|
53
|
+
# Makefile
|
|
54
|
+
[Makefile]
|
|
55
|
+
indent_style = tab
|
|
56
|
+
|
|
57
|
+
# Bats test files
|
|
58
|
+
[*.bats]
|
|
59
|
+
indent_style = space
|
|
60
|
+
indent_size = 4
|
package/.eslintrc.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"env": {
|
|
3
|
+
"node": true,
|
|
4
|
+
"es2022": true,
|
|
5
|
+
"jest": true
|
|
6
|
+
},
|
|
7
|
+
"parserOptions": {
|
|
8
|
+
"ecmaVersion": 2022,
|
|
9
|
+
"sourceType": "commonjs"
|
|
10
|
+
},
|
|
11
|
+
"extends": ["eslint:recommended"],
|
|
12
|
+
"rules": {
|
|
13
|
+
"indent": ["error", 4],
|
|
14
|
+
"linebreak-style": ["error", "unix"],
|
|
15
|
+
"quotes": ["error", "single", { "avoidEscape": true }],
|
|
16
|
+
"semi": ["error", "always"],
|
|
17
|
+
"no-unused-vars": ["error", { "argsIgnorePattern": "^_" }],
|
|
18
|
+
"no-console": "off",
|
|
19
|
+
"eqeqeq": ["error", "always"],
|
|
20
|
+
"curly": ["error", "all"],
|
|
21
|
+
"brace-style": ["error", "1tbs"],
|
|
22
|
+
"comma-dangle": ["error", "only-multiline"],
|
|
23
|
+
"comma-spacing": ["error", { "before": false, "after": true }],
|
|
24
|
+
"keyword-spacing": ["error", { "before": true, "after": true }],
|
|
25
|
+
"space-before-blocks": ["error", "always"],
|
|
26
|
+
"object-curly-spacing": ["error", "always"],
|
|
27
|
+
"array-bracket-spacing": ["error", "never"],
|
|
28
|
+
"no-trailing-spaces": "error",
|
|
29
|
+
"eol-last": ["error", "always"],
|
|
30
|
+
"max-len": ["warn", { "code": 100, "ignoreStrings": true, "ignoreTemplateLiterals": true }],
|
|
31
|
+
"prefer-const": "error",
|
|
32
|
+
"no-var": "error"
|
|
33
|
+
},
|
|
34
|
+
"ignorePatterns": ["node_modules/", "coverage/", "*.min.js"]
|
|
35
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
# GitHub Actions
|
|
4
|
+
- package-ecosystem: "github-actions"
|
|
5
|
+
directory: "/"
|
|
6
|
+
schedule:
|
|
7
|
+
interval: "weekly"
|
|
8
|
+
day: "monday"
|
|
9
|
+
commit-message:
|
|
10
|
+
prefix: "ci"
|
|
11
|
+
labels:
|
|
12
|
+
- "dependencies"
|
|
13
|
+
- "github-actions"
|
|
14
|
+
|
|
15
|
+
# npm dependencies
|
|
16
|
+
- package-ecosystem: "npm"
|
|
17
|
+
directory: "/"
|
|
18
|
+
schedule:
|
|
19
|
+
interval: "weekly"
|
|
20
|
+
day: "monday"
|
|
21
|
+
commit-message:
|
|
22
|
+
prefix: "deps"
|
|
23
|
+
labels:
|
|
24
|
+
- "dependencies"
|
|
25
|
+
- "javascript"
|
|
26
|
+
groups:
|
|
27
|
+
dev-dependencies:
|
|
28
|
+
patterns:
|
|
29
|
+
- "*"
|
|
30
|
+
update-types:
|
|
31
|
+
- "minor"
|
|
32
|
+
- "patch"
|
|
33
|
+
|
|
34
|
+
# pip dependencies
|
|
35
|
+
- package-ecosystem: "pip"
|
|
36
|
+
directory: "/"
|
|
37
|
+
schedule:
|
|
38
|
+
interval: "weekly"
|
|
39
|
+
day: "monday"
|
|
40
|
+
commit-message:
|
|
41
|
+
prefix: "deps"
|
|
42
|
+
labels:
|
|
43
|
+
- "dependencies"
|
|
44
|
+
- "python"
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
concurrency:
|
|
10
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
11
|
+
cancel-in-progress: true
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
# ============================================
|
|
15
|
+
# BASH SCRIPTS - LINT AND TEST
|
|
16
|
+
# ============================================
|
|
17
|
+
bash-lint:
|
|
18
|
+
name: Bash Lint (ShellCheck)
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
steps:
|
|
21
|
+
- name: Checkout
|
|
22
|
+
uses: actions/checkout@v4
|
|
23
|
+
|
|
24
|
+
- name: Run ShellCheck
|
|
25
|
+
uses: ludeeus/action-shellcheck@master
|
|
26
|
+
with:
|
|
27
|
+
scandir: './scripts'
|
|
28
|
+
additional_files: 'install.sh'
|
|
29
|
+
severity: warning
|
|
30
|
+
format: tty
|
|
31
|
+
|
|
32
|
+
bash-test:
|
|
33
|
+
name: Bash Tests (${{ matrix.os }})
|
|
34
|
+
needs: bash-lint
|
|
35
|
+
runs-on: ${{ matrix.os }}
|
|
36
|
+
strategy:
|
|
37
|
+
fail-fast: false
|
|
38
|
+
matrix:
|
|
39
|
+
os: [ubuntu-latest, macos-latest]
|
|
40
|
+
steps:
|
|
41
|
+
- name: Checkout
|
|
42
|
+
uses: actions/checkout@v4
|
|
43
|
+
|
|
44
|
+
- name: Install jq
|
|
45
|
+
run: |
|
|
46
|
+
if [[ "$RUNNER_OS" == "Linux" ]]; then
|
|
47
|
+
sudo apt-get update && sudo apt-get install -y jq
|
|
48
|
+
elif [[ "$RUNNER_OS" == "macOS" ]]; then
|
|
49
|
+
brew install jq
|
|
50
|
+
fi
|
|
51
|
+
|
|
52
|
+
- name: Install Bats
|
|
53
|
+
run: |
|
|
54
|
+
if [[ "$RUNNER_OS" == "Linux" ]]; then
|
|
55
|
+
sudo apt-get install -y bats
|
|
56
|
+
elif [[ "$RUNNER_OS" == "macOS" ]]; then
|
|
57
|
+
brew install bats-core
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
- name: Run Bats tests
|
|
61
|
+
run: bats tests/bash/*.bats
|
|
62
|
+
|
|
63
|
+
# ============================================
|
|
64
|
+
# PYTHON SCRIPT - LINT AND TEST
|
|
65
|
+
# ============================================
|
|
66
|
+
python-lint:
|
|
67
|
+
name: Python Lint
|
|
68
|
+
runs-on: ubuntu-latest
|
|
69
|
+
steps:
|
|
70
|
+
- name: Checkout
|
|
71
|
+
uses: actions/checkout@v4
|
|
72
|
+
|
|
73
|
+
- name: Set up Python
|
|
74
|
+
uses: actions/setup-python@v5
|
|
75
|
+
with:
|
|
76
|
+
python-version: '3.11'
|
|
77
|
+
cache: 'pip'
|
|
78
|
+
cache-dependency-path: 'requirements-dev.txt'
|
|
79
|
+
|
|
80
|
+
- name: Install dependencies
|
|
81
|
+
run: pip install -r requirements-dev.txt
|
|
82
|
+
|
|
83
|
+
- name: Run Ruff (linting)
|
|
84
|
+
run: ruff check scripts/statusline.py
|
|
85
|
+
|
|
86
|
+
- name: Run Ruff (formatting check)
|
|
87
|
+
run: ruff format --check scripts/statusline.py
|
|
88
|
+
|
|
89
|
+
- name: Run MyPy (type checking)
|
|
90
|
+
run: mypy scripts/statusline.py --ignore-missing-imports
|
|
91
|
+
|
|
92
|
+
python-test:
|
|
93
|
+
name: Python Tests (${{ matrix.os }}, Python ${{ matrix.python-version }})
|
|
94
|
+
needs: python-lint
|
|
95
|
+
runs-on: ${{ matrix.os }}
|
|
96
|
+
strategy:
|
|
97
|
+
fail-fast: false
|
|
98
|
+
matrix:
|
|
99
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
100
|
+
python-version: ['3.9', '3.10', '3.11', '3.12']
|
|
101
|
+
steps:
|
|
102
|
+
- name: Checkout
|
|
103
|
+
uses: actions/checkout@v4
|
|
104
|
+
|
|
105
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
106
|
+
uses: actions/setup-python@v5
|
|
107
|
+
with:
|
|
108
|
+
python-version: ${{ matrix.python-version }}
|
|
109
|
+
cache: 'pip'
|
|
110
|
+
cache-dependency-path: 'requirements-dev.txt'
|
|
111
|
+
|
|
112
|
+
- name: Install dependencies
|
|
113
|
+
run: pip install -r requirements-dev.txt
|
|
114
|
+
|
|
115
|
+
- name: Run pytest with coverage
|
|
116
|
+
run: pytest tests/python/ -v --cov=scripts --cov-report=xml --cov-report=term
|
|
117
|
+
|
|
118
|
+
- name: Upload coverage to Codecov
|
|
119
|
+
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.11'
|
|
120
|
+
uses: codecov/codecov-action@v4
|
|
121
|
+
with:
|
|
122
|
+
files: ./coverage.xml
|
|
123
|
+
flags: python
|
|
124
|
+
fail_ci_if_error: false
|
|
125
|
+
|
|
126
|
+
# ============================================
|
|
127
|
+
# NODE.JS SCRIPT - LINT AND TEST
|
|
128
|
+
# ============================================
|
|
129
|
+
node-lint:
|
|
130
|
+
name: Node.js Lint
|
|
131
|
+
runs-on: ubuntu-latest
|
|
132
|
+
steps:
|
|
133
|
+
- name: Checkout
|
|
134
|
+
uses: actions/checkout@v4
|
|
135
|
+
|
|
136
|
+
- name: Set up Node.js
|
|
137
|
+
uses: actions/setup-node@v4
|
|
138
|
+
with:
|
|
139
|
+
node-version: '20'
|
|
140
|
+
cache: 'npm'
|
|
141
|
+
|
|
142
|
+
- name: Install dependencies
|
|
143
|
+
run: npm ci
|
|
144
|
+
|
|
145
|
+
- name: Run ESLint
|
|
146
|
+
run: npx eslint scripts/statusline.js
|
|
147
|
+
|
|
148
|
+
- name: Run Prettier check
|
|
149
|
+
run: npx prettier --check scripts/statusline.js
|
|
150
|
+
|
|
151
|
+
node-test:
|
|
152
|
+
name: Node.js Tests (${{ matrix.os }}, Node ${{ matrix.node-version }})
|
|
153
|
+
needs: node-lint
|
|
154
|
+
runs-on: ${{ matrix.os }}
|
|
155
|
+
strategy:
|
|
156
|
+
fail-fast: false
|
|
157
|
+
matrix:
|
|
158
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
159
|
+
node-version: ['18', '20', '22']
|
|
160
|
+
steps:
|
|
161
|
+
- name: Checkout
|
|
162
|
+
uses: actions/checkout@v4
|
|
163
|
+
|
|
164
|
+
- name: Set up Node.js ${{ matrix.node-version }}
|
|
165
|
+
uses: actions/setup-node@v4
|
|
166
|
+
with:
|
|
167
|
+
node-version: ${{ matrix.node-version }}
|
|
168
|
+
cache: 'npm'
|
|
169
|
+
|
|
170
|
+
- name: Install dependencies
|
|
171
|
+
run: npm ci
|
|
172
|
+
|
|
173
|
+
- name: Run Jest tests
|
|
174
|
+
run: npm test -- --coverage
|
|
175
|
+
|
|
176
|
+
- name: Upload coverage to Codecov
|
|
177
|
+
if: matrix.os == 'ubuntu-latest' && matrix.node-version == '20'
|
|
178
|
+
uses: codecov/codecov-action@v4
|
|
179
|
+
with:
|
|
180
|
+
files: ./coverage/node/lcov.info
|
|
181
|
+
flags: node
|
|
182
|
+
fail_ci_if_error: false
|
|
183
|
+
|
|
184
|
+
# ============================================
|
|
185
|
+
# INTEGRATION TESTS
|
|
186
|
+
# ============================================
|
|
187
|
+
integration-test:
|
|
188
|
+
name: Integration Tests (${{ matrix.os }})
|
|
189
|
+
needs: [bash-test, python-test, node-test]
|
|
190
|
+
runs-on: ${{ matrix.os }}
|
|
191
|
+
strategy:
|
|
192
|
+
fail-fast: false
|
|
193
|
+
matrix:
|
|
194
|
+
os: [ubuntu-latest, macos-latest]
|
|
195
|
+
steps:
|
|
196
|
+
- name: Checkout
|
|
197
|
+
uses: actions/checkout@v4
|
|
198
|
+
|
|
199
|
+
- name: Install jq
|
|
200
|
+
run: |
|
|
201
|
+
if [[ "$RUNNER_OS" == "Linux" ]]; then
|
|
202
|
+
sudo apt-get update && sudo apt-get install -y jq
|
|
203
|
+
elif [[ "$RUNNER_OS" == "macOS" ]]; then
|
|
204
|
+
brew install jq
|
|
205
|
+
fi
|
|
206
|
+
|
|
207
|
+
- name: Set up Python
|
|
208
|
+
uses: actions/setup-python@v5
|
|
209
|
+
with:
|
|
210
|
+
python-version: '3.11'
|
|
211
|
+
|
|
212
|
+
- name: Set up Node.js
|
|
213
|
+
uses: actions/setup-node@v4
|
|
214
|
+
with:
|
|
215
|
+
node-version: '20'
|
|
216
|
+
|
|
217
|
+
- name: Run integration tests
|
|
218
|
+
run: |
|
|
219
|
+
SAMPLE_INPUT='{"model":{"display_name":"Claude 3.5 Sonnet"},"workspace":{"current_dir":"/tmp/test","project_dir":"/tmp/test"},"context_window":{"context_window_size":200000,"current_usage":{"input_tokens":1000,"cache_creation_input_tokens":500,"cache_read_input_tokens":200}}}'
|
|
220
|
+
|
|
221
|
+
echo "Testing bash scripts..."
|
|
222
|
+
echo "$SAMPLE_INPUT" | ./scripts/statusline-full.sh
|
|
223
|
+
echo "$SAMPLE_INPUT" | ./scripts/statusline-git.sh
|
|
224
|
+
echo "$SAMPLE_INPUT" | ./scripts/statusline-minimal.sh
|
|
225
|
+
|
|
226
|
+
echo "Testing Python script..."
|
|
227
|
+
echo "$SAMPLE_INPUT" | python3 ./scripts/statusline.py
|
|
228
|
+
|
|
229
|
+
echo "Testing Node.js script..."
|
|
230
|
+
echo "$SAMPLE_INPUT" | node ./scripts/statusline.js
|
|
231
|
+
|
|
232
|
+
echo "All integration tests passed!"
|
|
233
|
+
|
|
234
|
+
# ============================================
|
|
235
|
+
# FINAL STATUS CHECK
|
|
236
|
+
# ============================================
|
|
237
|
+
ci-success:
|
|
238
|
+
name: CI Success
|
|
239
|
+
needs: [bash-lint, bash-test, python-lint, python-test, node-lint, node-test, integration-test]
|
|
240
|
+
runs-on: ubuntu-latest
|
|
241
|
+
if: always()
|
|
242
|
+
steps:
|
|
243
|
+
- name: Check all jobs passed
|
|
244
|
+
run: |
|
|
245
|
+
if [[ "${{ needs.bash-lint.result }}" != "success" ]] || \
|
|
246
|
+
[[ "${{ needs.bash-test.result }}" != "success" ]] || \
|
|
247
|
+
[[ "${{ needs.python-lint.result }}" != "success" ]] || \
|
|
248
|
+
[[ "${{ needs.python-test.result }}" != "success" ]] || \
|
|
249
|
+
[[ "${{ needs.node-lint.result }}" != "success" ]] || \
|
|
250
|
+
[[ "${{ needs.node-test.result }}" != "success" ]] || \
|
|
251
|
+
[[ "${{ needs.integration-test.result }}" != "success" ]]; then
|
|
252
|
+
echo "One or more jobs failed"
|
|
253
|
+
exit 1
|
|
254
|
+
fi
|
|
255
|
+
echo "All CI jobs passed successfully!"
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- 'v*'
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
inputs:
|
|
9
|
+
version:
|
|
10
|
+
description: 'Version to release (e.g., 1.2.0)'
|
|
11
|
+
required: true
|
|
12
|
+
type: string
|
|
13
|
+
|
|
14
|
+
permissions:
|
|
15
|
+
contents: write
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
validate:
|
|
19
|
+
name: Validate Release
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
outputs:
|
|
22
|
+
version: ${{ steps.version.outputs.version }}
|
|
23
|
+
steps:
|
|
24
|
+
- name: Checkout
|
|
25
|
+
uses: actions/checkout@v4
|
|
26
|
+
with:
|
|
27
|
+
fetch-depth: 0
|
|
28
|
+
|
|
29
|
+
- name: Determine version
|
|
30
|
+
id: version
|
|
31
|
+
run: |
|
|
32
|
+
if [[ "${{ github.event_name }}" == "push" ]]; then
|
|
33
|
+
VERSION="${GITHUB_REF#refs/tags/v}"
|
|
34
|
+
else
|
|
35
|
+
VERSION="${{ github.event.inputs.version }}"
|
|
36
|
+
fi
|
|
37
|
+
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
|
38
|
+
echo "Release version: $VERSION"
|
|
39
|
+
|
|
40
|
+
- name: Validate version format
|
|
41
|
+
run: |
|
|
42
|
+
VERSION="${{ steps.version.outputs.version }}"
|
|
43
|
+
if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9]+)?$ ]]; then
|
|
44
|
+
echo "Invalid version format: $VERSION"
|
|
45
|
+
echo "Expected format: X.Y.Z or X.Y.Z-suffix"
|
|
46
|
+
exit 1
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
test:
|
|
50
|
+
name: Run Tests
|
|
51
|
+
needs: validate
|
|
52
|
+
runs-on: ubuntu-latest
|
|
53
|
+
steps:
|
|
54
|
+
- name: Checkout
|
|
55
|
+
uses: actions/checkout@v4
|
|
56
|
+
|
|
57
|
+
- name: Set up Python
|
|
58
|
+
uses: actions/setup-python@v5
|
|
59
|
+
with:
|
|
60
|
+
python-version: '3.11'
|
|
61
|
+
|
|
62
|
+
- name: Set up Node.js
|
|
63
|
+
uses: actions/setup-node@v4
|
|
64
|
+
with:
|
|
65
|
+
node-version: '20'
|
|
66
|
+
cache: 'npm'
|
|
67
|
+
|
|
68
|
+
- name: Install jq
|
|
69
|
+
run: sudo apt-get update && sudo apt-get install -y jq bats
|
|
70
|
+
|
|
71
|
+
- name: Install Python dependencies
|
|
72
|
+
run: pip install -r requirements-dev.txt
|
|
73
|
+
|
|
74
|
+
- name: Install Node.js dependencies
|
|
75
|
+
run: npm ci
|
|
76
|
+
|
|
77
|
+
- name: Run Python tests
|
|
78
|
+
run: pytest tests/python/ -v
|
|
79
|
+
|
|
80
|
+
- name: Run Node.js tests
|
|
81
|
+
run: npm test
|
|
82
|
+
|
|
83
|
+
- name: Run Bash tests
|
|
84
|
+
run: bats tests/bash/*.bats
|
|
85
|
+
|
|
86
|
+
create-release:
|
|
87
|
+
name: Create GitHub Release
|
|
88
|
+
needs: [validate, test]
|
|
89
|
+
runs-on: ubuntu-latest
|
|
90
|
+
steps:
|
|
91
|
+
- name: Checkout
|
|
92
|
+
uses: actions/checkout@v4
|
|
93
|
+
with:
|
|
94
|
+
fetch-depth: 0
|
|
95
|
+
|
|
96
|
+
- name: Generate changelog
|
|
97
|
+
id: changelog
|
|
98
|
+
run: |
|
|
99
|
+
# Get commits since last tag
|
|
100
|
+
LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
|
|
101
|
+
if [ -n "$LAST_TAG" ]; then
|
|
102
|
+
COMMITS=$(git log --pretty=format:"- %s" "$LAST_TAG"..HEAD)
|
|
103
|
+
else
|
|
104
|
+
COMMITS=$(git log --pretty=format:"- %s")
|
|
105
|
+
fi
|
|
106
|
+
|
|
107
|
+
# Create changelog
|
|
108
|
+
{
|
|
109
|
+
echo 'changelog<<EOF'
|
|
110
|
+
echo "## What's Changed"
|
|
111
|
+
echo ""
|
|
112
|
+
echo "$COMMITS"
|
|
113
|
+
echo ""
|
|
114
|
+
echo "**Full Changelog**: https://github.com/${{ github.repository }}/compare/${LAST_TAG}...v${{ needs.validate.outputs.version }}"
|
|
115
|
+
echo 'EOF'
|
|
116
|
+
} >> $GITHUB_OUTPUT
|
|
117
|
+
|
|
118
|
+
- name: Create Release Archive
|
|
119
|
+
run: |
|
|
120
|
+
VERSION="${{ needs.validate.outputs.version }}"
|
|
121
|
+
mkdir -p dist
|
|
122
|
+
|
|
123
|
+
# Create tarball
|
|
124
|
+
tar -czf dist/claude-statusline-${VERSION}.tar.gz \
|
|
125
|
+
scripts/ \
|
|
126
|
+
config/ \
|
|
127
|
+
install.sh \
|
|
128
|
+
README.md
|
|
129
|
+
|
|
130
|
+
# Create zip
|
|
131
|
+
zip -r dist/claude-statusline-${VERSION}.zip \
|
|
132
|
+
scripts/ \
|
|
133
|
+
config/ \
|
|
134
|
+
install.sh \
|
|
135
|
+
README.md
|
|
136
|
+
|
|
137
|
+
- name: Create GitHub Release
|
|
138
|
+
uses: softprops/action-gh-release@v2
|
|
139
|
+
with:
|
|
140
|
+
tag_name: v${{ needs.validate.outputs.version }}
|
|
141
|
+
name: Release v${{ needs.validate.outputs.version }}
|
|
142
|
+
body: ${{ steps.changelog.outputs.changelog }}
|
|
143
|
+
draft: false
|
|
144
|
+
prerelease: ${{ contains(needs.validate.outputs.version, '-') }}
|
|
145
|
+
files: |
|
|
146
|
+
dist/claude-statusline-*.tar.gz
|
|
147
|
+
dist/claude-statusline-*.zip
|
|
148
|
+
env:
|
|
149
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|