dashboard-for-claude-code 0.1.0__tar.gz
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.
- dashboard_for_claude_code-0.1.0/.github/ISSUE_TEMPLATE/bug_report.md +32 -0
- dashboard_for_claude_code-0.1.0/.github/ISSUE_TEMPLATE/config.yml +5 -0
- dashboard_for_claude_code-0.1.0/.github/ISSUE_TEMPLATE/feature_request.md +23 -0
- dashboard_for_claude_code-0.1.0/.github/PULL_REQUEST_TEMPLATE.md +12 -0
- dashboard_for_claude_code-0.1.0/.github/dependabot.yml +18 -0
- dashboard_for_claude_code-0.1.0/.github/workflows/ci.yml +50 -0
- dashboard_for_claude_code-0.1.0/.github/workflows/publish.yml +100 -0
- dashboard_for_claude_code-0.1.0/.github/workflows/security.yml +61 -0
- dashboard_for_claude_code-0.1.0/.gitignore +63 -0
- dashboard_for_claude_code-0.1.0/CHANGELOG.md +43 -0
- dashboard_for_claude_code-0.1.0/CLAUDE_README.md +136 -0
- dashboard_for_claude_code-0.1.0/CODE_OF_CONDUCT.md +46 -0
- dashboard_for_claude_code-0.1.0/CONTRIBUTING.md +42 -0
- dashboard_for_claude_code-0.1.0/LICENSE +21 -0
- dashboard_for_claude_code-0.1.0/PKG-INFO +277 -0
- dashboard_for_claude_code-0.1.0/README.md +250 -0
- dashboard_for_claude_code-0.1.0/SECURITY.md +26 -0
- dashboard_for_claude_code-0.1.0/docs/autonomy-skills.png +0 -0
- dashboard_for_claude_code-0.1.0/docs/banner.jpeg +0 -0
- dashboard_for_claude_code-0.1.0/docs/calendar.png +0 -0
- dashboard_for_claude_code-0.1.0/docs/heatmap.png +0 -0
- dashboard_for_claude_code-0.1.0/docs/overview.png +0 -0
- dashboard_for_claude_code-0.1.0/docs/projects-cost.png +0 -0
- dashboard_for_claude_code-0.1.0/docs/projects.png +0 -0
- dashboard_for_claude_code-0.1.0/docs/session-detail.png +0 -0
- dashboard_for_claude_code-0.1.0/docs/settings.png +0 -0
- dashboard_for_claude_code-0.1.0/pyproject.toml +80 -0
- dashboard_for_claude_code-0.1.0/scripts/README.md +85 -0
- dashboard_for_claude_code-0.1.0/scripts/SECURITY.md +74 -0
- dashboard_for_claude_code-0.1.0/scripts/com.claude-dashboard.plist.example +40 -0
- dashboard_for_claude_code-0.1.0/scripts/demo_data.py +250 -0
- dashboard_for_claude_code-0.1.0/scripts/deploy.env.example +5 -0
- dashboard_for_claude_code-0.1.0/scripts/deploy.sh +35 -0
- dashboard_for_claude_code-0.1.0/scripts/export.py +168 -0
- dashboard_for_claude_code-0.1.0/scripts/refresh.sh +75 -0
- dashboard_for_claude_code-0.1.0/scripts/session_digest.py +165 -0
- dashboard_for_claude_code-0.1.0/scripts/set_summaries.py +70 -0
- dashboard_for_claude_code-0.1.0/src/claude_dashboard/__init__.py +0 -0
- dashboard_for_claude_code-0.1.0/src/claude_dashboard/__main__.py +55 -0
- dashboard_for_claude_code-0.1.0/src/claude_dashboard/app.py +276 -0
- dashboard_for_claude_code-0.1.0/src/claude_dashboard/parser.py +370 -0
- dashboard_for_claude_code-0.1.0/src/claude_dashboard/pricing.py +91 -0
- dashboard_for_claude_code-0.1.0/src/claude_dashboard/scanner.py +176 -0
- dashboard_for_claude_code-0.1.0/src/claude_dashboard/static/app.js +2799 -0
- dashboard_for_claude_code-0.1.0/src/claude_dashboard/static/chart.umd.min.js +20 -0
- dashboard_for_claude_code-0.1.0/src/claude_dashboard/static/index.html +273 -0
- dashboard_for_claude_code-0.1.0/src/claude_dashboard/static/styles.css +1109 -0
- dashboard_for_claude_code-0.1.0/src/claude_dashboard/store.py +591 -0
- dashboard_for_claude_code-0.1.0/tests/__init__.py +0 -0
- dashboard_for_claude_code-0.1.0/tests/fixtures/tiny_session.jsonl +7 -0
- dashboard_for_claude_code-0.1.0/tests/test_app.py +254 -0
- dashboard_for_claude_code-0.1.0/tests/test_demo_data.py +62 -0
- dashboard_for_claude_code-0.1.0/tests/test_export.py +135 -0
- dashboard_for_claude_code-0.1.0/tests/test_main.py +81 -0
- dashboard_for_claude_code-0.1.0/tests/test_parser.py +171 -0
- dashboard_for_claude_code-0.1.0/tests/test_pricing.py +101 -0
- dashboard_for_claude_code-0.1.0/tests/test_scanner.py +97 -0
- dashboard_for_claude_code-0.1.0/tests/test_session_digest.py +72 -0
- dashboard_for_claude_code-0.1.0/tests/test_set_summaries.py +79 -0
- dashboard_for_claude_code-0.1.0/tests/test_store.py +264 -0
- dashboard_for_claude_code-0.1.0/uv.lock +759 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Bug report
|
|
3
|
+
about: Something is broken or behaving unexpectedly
|
|
4
|
+
labels: bug
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## What happened
|
|
8
|
+
|
|
9
|
+
<!-- A clear description of the bug. -->
|
|
10
|
+
|
|
11
|
+
## Steps to reproduce
|
|
12
|
+
|
|
13
|
+
1.
|
|
14
|
+
2.
|
|
15
|
+
3.
|
|
16
|
+
|
|
17
|
+
## Expected behavior
|
|
18
|
+
|
|
19
|
+
## Environment
|
|
20
|
+
|
|
21
|
+
- OS:
|
|
22
|
+
- Python version (`python3 --version`):
|
|
23
|
+
- Install method (clone + uv / pipx / uvx):
|
|
24
|
+
- Claude Code version (from a session, or `claude --version`):
|
|
25
|
+
|
|
26
|
+
## Logs / JSONL snippet (optional)
|
|
27
|
+
|
|
28
|
+
<!--
|
|
29
|
+
If the bug involves parsing, a REDACTED snippet of the relevant session JSONL
|
|
30
|
+
helps a lot. Remove file paths, prompt text, and anything personal first —
|
|
31
|
+
see CONTRIBUTING.md.
|
|
32
|
+
-->
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Feature request
|
|
3
|
+
about: Suggest an improvement or new capability
|
|
4
|
+
labels: enhancement
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Problem
|
|
8
|
+
|
|
9
|
+
<!-- What are you trying to do that the dashboard doesn't support today? -->
|
|
10
|
+
|
|
11
|
+
## Proposed solution
|
|
12
|
+
|
|
13
|
+
<!-- What would you like to happen? Sketches/mockups welcome. -->
|
|
14
|
+
|
|
15
|
+
## Alternatives considered
|
|
16
|
+
|
|
17
|
+
## Notes
|
|
18
|
+
|
|
19
|
+
<!--
|
|
20
|
+
Keep in mind the project's constraints: local-first, read-only over
|
|
21
|
+
~/.claude/projects, no external network calls by default, vanilla JS UI
|
|
22
|
+
with no build step.
|
|
23
|
+
-->
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
## What & why
|
|
2
|
+
|
|
3
|
+
<!-- Summary of the change and the motivation. Link related issues. -->
|
|
4
|
+
|
|
5
|
+
## Checklist
|
|
6
|
+
|
|
7
|
+
- [ ] `uv run --group dev pytest` passes
|
|
8
|
+
- [ ] `uv run --group dev ruff check .` passes
|
|
9
|
+
- [ ] Stays local-first and read-only (no writes to `~/.claude`, no network
|
|
10
|
+
calls that aren't strictly opt-in)
|
|
11
|
+
- [ ] No personal data in the diff (paths, prompts, real project names)
|
|
12
|
+
- [ ] Tests added/adjusted for parsing, pricing, or export changes
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: github-actions
|
|
4
|
+
directory: /
|
|
5
|
+
schedule:
|
|
6
|
+
interval: weekly
|
|
7
|
+
groups:
|
|
8
|
+
# init and analyze must run the same version, so bump them in one PR.
|
|
9
|
+
# Split across two PRs, each fails: "Loaded a configuration file for
|
|
10
|
+
# version 'X', but running version 'Y'".
|
|
11
|
+
codeql-action:
|
|
12
|
+
patterns:
|
|
13
|
+
- "github/codeql-action*"
|
|
14
|
+
|
|
15
|
+
- package-ecosystem: uv
|
|
16
|
+
directory: /
|
|
17
|
+
schedule:
|
|
18
|
+
interval: weekly
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
lint:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
steps:
|
|
12
|
+
- uses: actions/checkout@v7.0.1
|
|
13
|
+
|
|
14
|
+
- name: Install uv
|
|
15
|
+
uses: astral-sh/setup-uv@v7
|
|
16
|
+
with:
|
|
17
|
+
enable-cache: true
|
|
18
|
+
|
|
19
|
+
- name: Check lockfile is up to date
|
|
20
|
+
run: uv lock --check
|
|
21
|
+
|
|
22
|
+
- name: Install dependencies
|
|
23
|
+
run: uv sync --group dev
|
|
24
|
+
|
|
25
|
+
- name: Ruff lint
|
|
26
|
+
run: uv run --group dev ruff check .
|
|
27
|
+
|
|
28
|
+
test:
|
|
29
|
+
runs-on: ubuntu-latest
|
|
30
|
+
strategy:
|
|
31
|
+
fail-fast: false
|
|
32
|
+
matrix:
|
|
33
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
34
|
+
|
|
35
|
+
steps:
|
|
36
|
+
- uses: actions/checkout@v7.0.1
|
|
37
|
+
|
|
38
|
+
- name: Install uv
|
|
39
|
+
uses: astral-sh/setup-uv@v7
|
|
40
|
+
with:
|
|
41
|
+
enable-cache: true
|
|
42
|
+
|
|
43
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
44
|
+
run: uv python install ${{ matrix.python-version }}
|
|
45
|
+
|
|
46
|
+
- name: Install dependencies
|
|
47
|
+
run: uv sync --python ${{ matrix.python-version }} --group dev
|
|
48
|
+
|
|
49
|
+
- name: Run tests
|
|
50
|
+
run: uv run --python ${{ matrix.python-version }} --group dev pytest -q
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
name: Publish
|
|
2
|
+
|
|
3
|
+
# Publishes to PyPI via Trusted Publishing (OIDC) — no API token is stored.
|
|
4
|
+
# The pending publisher registered on PyPI must match this file's name
|
|
5
|
+
# (publish.yml), the environment below (pypi), and this repository.
|
|
6
|
+
#
|
|
7
|
+
# To cut a release: bump `version` in pyproject.toml, merge to main, then
|
|
8
|
+
# git tag v0.1.0 && git push origin v0.1.0
|
|
9
|
+
# PyPI versions are immutable — a tag can never be republished.
|
|
10
|
+
|
|
11
|
+
on:
|
|
12
|
+
push:
|
|
13
|
+
tags: ["v*"]
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
# Re-run the full test matrix against the exact tagged commit. CI on main is
|
|
17
|
+
# not enough: the tag is what ships, and an unpublishable build is far cheaper
|
|
18
|
+
# to catch here than after a version number is permanently burned.
|
|
19
|
+
test:
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
strategy:
|
|
22
|
+
fail-fast: false
|
|
23
|
+
matrix:
|
|
24
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
25
|
+
|
|
26
|
+
steps:
|
|
27
|
+
- uses: actions/checkout@v7.0.1
|
|
28
|
+
|
|
29
|
+
- name: Install uv
|
|
30
|
+
uses: astral-sh/setup-uv@v7
|
|
31
|
+
with:
|
|
32
|
+
enable-cache: true
|
|
33
|
+
|
|
34
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
35
|
+
run: uv python install ${{ matrix.python-version }}
|
|
36
|
+
|
|
37
|
+
- name: Install dependencies
|
|
38
|
+
run: uv sync --python ${{ matrix.python-version }} --group dev
|
|
39
|
+
|
|
40
|
+
- name: Run tests
|
|
41
|
+
run: uv run --python ${{ matrix.python-version }} --group dev pytest -q
|
|
42
|
+
|
|
43
|
+
build:
|
|
44
|
+
needs: test
|
|
45
|
+
runs-on: ubuntu-latest
|
|
46
|
+
|
|
47
|
+
steps:
|
|
48
|
+
- uses: actions/checkout@v7.0.1
|
|
49
|
+
|
|
50
|
+
- name: Install uv
|
|
51
|
+
uses: astral-sh/setup-uv@v7
|
|
52
|
+
with:
|
|
53
|
+
enable-cache: true
|
|
54
|
+
|
|
55
|
+
# A tag that disagrees with pyproject.toml would publish a version nobody
|
|
56
|
+
# asked for, under a number that can never be reused. Fail before building.
|
|
57
|
+
- name: Check tag matches pyproject version
|
|
58
|
+
run: |
|
|
59
|
+
tag="${GITHUB_REF_NAME#v}"
|
|
60
|
+
project="$(uv version --short)"
|
|
61
|
+
if [ "$tag" != "$project" ]; then
|
|
62
|
+
echo "::error::Tag $GITHUB_REF_NAME implies version '$tag' but pyproject.toml declares '$project'."
|
|
63
|
+
exit 1
|
|
64
|
+
fi
|
|
65
|
+
echo "Publishing version $project"
|
|
66
|
+
|
|
67
|
+
- name: Build sdist and wheel
|
|
68
|
+
run: uv build
|
|
69
|
+
|
|
70
|
+
- name: Verify artifact metadata
|
|
71
|
+
run: uvx twine check dist/*
|
|
72
|
+
|
|
73
|
+
- uses: actions/upload-artifact@v4
|
|
74
|
+
with:
|
|
75
|
+
name: dist
|
|
76
|
+
path: dist/
|
|
77
|
+
|
|
78
|
+
publish:
|
|
79
|
+
needs: build
|
|
80
|
+
runs-on: ubuntu-latest
|
|
81
|
+
|
|
82
|
+
# Must match the environment name on the PyPI pending publisher. Also a
|
|
83
|
+
# useful place to hang a required reviewer if you ever want manual sign-off.
|
|
84
|
+
environment:
|
|
85
|
+
name: pypi
|
|
86
|
+
url: https://pypi.org/p/dashboard-for-claude-code
|
|
87
|
+
|
|
88
|
+
# id-token lets the runner mint the short-lived OIDC token PyPI trades for
|
|
89
|
+
# an upload grant. This is the whole reason no secret needs to exist.
|
|
90
|
+
permissions:
|
|
91
|
+
id-token: write
|
|
92
|
+
|
|
93
|
+
steps:
|
|
94
|
+
- uses: actions/download-artifact@v4
|
|
95
|
+
with:
|
|
96
|
+
name: dist
|
|
97
|
+
path: dist/
|
|
98
|
+
|
|
99
|
+
- name: Publish to PyPI
|
|
100
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
name: Security
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
schedule:
|
|
8
|
+
# Mondays 04:27 UTC — re-scan against newly disclosed patterns/CVEs.
|
|
9
|
+
- cron: "27 4 * * 1"
|
|
10
|
+
|
|
11
|
+
# Least privilege by default; only the job that needs more opts in below.
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
|
|
15
|
+
concurrency:
|
|
16
|
+
group: security-${{ github.ref }}
|
|
17
|
+
cancel-in-progress: true
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
secret-scan:
|
|
21
|
+
name: Secret scan (gitleaks)
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
steps:
|
|
24
|
+
# Full history so gitleaks scans every commit, not just the tip.
|
|
25
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
26
|
+
with:
|
|
27
|
+
fetch-depth: 0
|
|
28
|
+
- uses: gitleaks/gitleaks-action@e0c47f4f8be36e29cdc102c57e68cb5cbf0e8d1e # v3.0.0
|
|
29
|
+
env:
|
|
30
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
31
|
+
|
|
32
|
+
bandit:
|
|
33
|
+
name: Python SAST (bandit)
|
|
34
|
+
runs-on: ubuntu-latest
|
|
35
|
+
steps:
|
|
36
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
37
|
+
- name: Install uv
|
|
38
|
+
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0
|
|
39
|
+
with:
|
|
40
|
+
enable-cache: true
|
|
41
|
+
- name: Install dependencies
|
|
42
|
+
run: uv sync --group security
|
|
43
|
+
# bandit is pinned + hash-verified via uv.lock (security group).
|
|
44
|
+
- name: Run bandit
|
|
45
|
+
run: uv run --group security bandit -c pyproject.toml -r src/claude_dashboard scripts
|
|
46
|
+
|
|
47
|
+
codeql:
|
|
48
|
+
name: CodeQL (SAST)
|
|
49
|
+
runs-on: ubuntu-latest
|
|
50
|
+
permissions:
|
|
51
|
+
contents: read
|
|
52
|
+
security-events: write # required to upload results to the Security tab
|
|
53
|
+
steps:
|
|
54
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
55
|
+
- name: Initialize CodeQL
|
|
56
|
+
uses: github/codeql-action/init@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3
|
|
57
|
+
with:
|
|
58
|
+
languages: python
|
|
59
|
+
queries: security-extended
|
|
60
|
+
- name: Analyze
|
|
61
|
+
uses: github/codeql-action/analyze@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Runtime data — contains personal metadata (project paths, session timestamps, usage stats)
|
|
2
|
+
data/
|
|
3
|
+
|
|
4
|
+
# Python
|
|
5
|
+
.venv/
|
|
6
|
+
__pycache__/
|
|
7
|
+
*.py[cod]
|
|
8
|
+
*.egg-info/
|
|
9
|
+
dist/
|
|
10
|
+
build/
|
|
11
|
+
.pytest_cache/
|
|
12
|
+
.ruff_cache/
|
|
13
|
+
.mypy_cache/
|
|
14
|
+
|
|
15
|
+
# Test coverage artifacts (regenerated by coverage.py / pytest-cov)
|
|
16
|
+
.coverage
|
|
17
|
+
.coverage.*
|
|
18
|
+
htmlcov/
|
|
19
|
+
coverage.xml
|
|
20
|
+
|
|
21
|
+
# Claude Code local state (memory, settings, plans)
|
|
22
|
+
.claude/
|
|
23
|
+
|
|
24
|
+
# Remote publish — generated by scripts/export.py, not source-controlled
|
|
25
|
+
remote_public/data/
|
|
26
|
+
remote_public/src/
|
|
27
|
+
remote_public/index.html
|
|
28
|
+
|
|
29
|
+
# Refresh state
|
|
30
|
+
logs/
|
|
31
|
+
.last_data_hash
|
|
32
|
+
|
|
33
|
+
# Local deploy config & personal launch agent — keep only the .example templates
|
|
34
|
+
scripts/deploy.env
|
|
35
|
+
scripts/*.plist
|
|
36
|
+
!scripts/*.plist.example
|
|
37
|
+
|
|
38
|
+
# OS
|
|
39
|
+
.DS_Store
|
|
40
|
+
|
|
41
|
+
# Local-only maintainer / agent notes (migration logs, origin pointer, review
|
|
42
|
+
# notes) — never published to the public repo
|
|
43
|
+
CLAUDE/
|
|
44
|
+
CLAUDE_REVIEW/
|
|
45
|
+
|
|
46
|
+
# AI assistant local files — instruction/rule files and chat history from coding
|
|
47
|
+
# assistants. Kept local so the public repo carries no assistant scaffolding.
|
|
48
|
+
# (The .claude/ state dir is already ignored above.)
|
|
49
|
+
CLAUDE.md
|
|
50
|
+
CLAUDE.local.md
|
|
51
|
+
GEMINI.md
|
|
52
|
+
# AGENTS.md is sometimes intentionally shared — un-ignore it if you want to publish it
|
|
53
|
+
AGENTS.md
|
|
54
|
+
.cursor/
|
|
55
|
+
.cursorrules
|
|
56
|
+
.cursorignore
|
|
57
|
+
.windsurf/
|
|
58
|
+
.windsurfrules
|
|
59
|
+
.aider*
|
|
60
|
+
.continue/
|
|
61
|
+
.clinerules
|
|
62
|
+
.roo/
|
|
63
|
+
.github/copilot-instructions.md
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [0.1.0] — 2026-07-08
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- Initial release.
|
|
7
|
+
- CLI flags on the entrypoint: `--help`, `--version`, and `--host`/`--port`
|
|
8
|
+
(which take precedence over `DASHBOARD_HOST`/`DASHBOARD_PORT`). Previously
|
|
9
|
+
any argument was silently ignored and the server just started.
|
|
10
|
+
- Read-only local dashboard for browsing Claude Code usage: projects, sessions,
|
|
11
|
+
cost/token breakdowns, tool-use stats, and per-session timelines.
|
|
12
|
+
- SQLite-backed scan cache (`data/usage.db`); rescans on startup and on-demand
|
|
13
|
+
via `POST /api/refresh`.
|
|
14
|
+
- Optional token auth (`DASHBOARD_AUTH_TOKEN`) with `HttpOnly`+`SameSite=strict`
|
|
15
|
+
cookie and constant-time comparison.
|
|
16
|
+
- Binds to `127.0.0.1` by default; set `DASHBOARD_HOST=0.0.0.0` to expose on the LAN.
|
|
17
|
+
- DNS-rebinding protection: Host-header allowlist when bound to loopback.
|
|
18
|
+
- Cookie `secure` flag enabled automatically for non-localhost deployments.
|
|
19
|
+
- CI on Python 3.11–3.13, plus ruff lint and lockfile checks.
|
|
20
|
+
- Security scanning in CI: gitleaks (secret scanning), bandit (Python SAST),
|
|
21
|
+
and CodeQL. Dev/security tooling lives in opt-in dependency groups, so a plain
|
|
22
|
+
`uv sync` installs runtime dependencies only.
|
|
23
|
+
- Demo data generator (`scripts/demo_data.py`) for screenshots and UI exploration.
|
|
24
|
+
- Optional prune on refresh (`POST /api/refresh?prune=true`) to drop sessions
|
|
25
|
+
whose transcript was deleted from disk; by default history is kept.
|
|
26
|
+
- Community files: code of conduct, issue/PR templates, dependabot config.
|
|
27
|
+
|
|
28
|
+
### Fixed
|
|
29
|
+
- Static export now redacts home-directory paths in dict keys too —
|
|
30
|
+
`settings.json` previously leaked absolute paths even with
|
|
31
|
+
`DASHBOARD_REDACT_HOME=1` (this also fixes settings lookups in remote mode).
|
|
32
|
+
- A transcript deleted mid-scan no longer aborts the background refresh.
|
|
33
|
+
- Default DB path for installed (pipx/uvx) packages now uses a per-user data
|
|
34
|
+
dir instead of a directory inside the virtualenv.
|
|
35
|
+
- Host-header guard now parses bracketed IPv6 hosts correctly and rejects
|
|
36
|
+
empty `Host` headers.
|
|
37
|
+
- SQLite cache uses WAL mode and a busy timeout for safer concurrent
|
|
38
|
+
reads during background scans.
|
|
39
|
+
- Future Opus model ids no longer silently match legacy (3×) pricing; unmatched
|
|
40
|
+
models are surfaced as unknown instead.
|
|
41
|
+
- `scripts/set_summaries.py` and `scripts/session_digest.py` follow
|
|
42
|
+
`DASHBOARD_DB` so summaries land next to the database actually in use.
|
|
43
|
+
- Hidden projects remain reachable via a direct detail link.
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# Claude Instructions — Dashboard for Claude Code
|
|
2
|
+
|
|
3
|
+
This file is written for Claude (AI assistant / Claude Code agent). Follow the steps below when a user asks you to set up, run, or configure this project. Do not skip steps or assume they have already been completed unless the user confirms.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Step 1 — Install dependencies
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
uv sync
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Confirm it exits without errors before proceeding.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Step 2 — Start the dashboard locally
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
uv run python -m claude_dashboard
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
The server starts at **http://localhost:8042**. On first run, all sessions are parsed in the background — the UI appears immediately and fills in as scanning completes. Tell the user to open that URL and confirm they can see the dashboard before continuing.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Step 3 — Ask the user about session summaries
|
|
28
|
+
|
|
29
|
+
Once the dashboard is confirmed running, ask the user:
|
|
30
|
+
|
|
31
|
+
> "The dashboard can show a one- or two-sentence summary on each session card. Would you like me to generate summaries for sessions that don't have one yet?"
|
|
32
|
+
|
|
33
|
+
**Before they agree, state the following clearly:**
|
|
34
|
+
|
|
35
|
+
- Generating summaries **uses your Claude Code agent tokens** — the same budget as any other Claude Code session.
|
|
36
|
+
- Each batch reads session content (first prompt, last assistant response, tools used) and writes a short summary. This is done locally; no data leaves your machine.
|
|
37
|
+
- If you have many unsummarized sessions this may take several rounds and could be **slow or cost more tokens than expected**. You can run it in batches and stop at any time.
|
|
38
|
+
- Summaries are stored in `data/session_summary.json` and picked up on the next dashboard refresh — no server restart needed.
|
|
39
|
+
|
|
40
|
+
If the user says no, stop here. If they say yes, continue to Step 4.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Step 4 — Generate and apply session summaries
|
|
45
|
+
|
|
46
|
+
### 4a. Check how many sessions need summaries
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
python scripts/session_digest.py 1 --offset 0
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
This prints the total count of sessions missing a summary. Show it to the user so they can decide how many to process at once. A reasonable batch size is 8 (the default).
|
|
53
|
+
|
|
54
|
+
### 4b. Read the digests
|
|
55
|
+
|
|
56
|
+
Run the digest script to see the batch:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
python scripts/session_digest.py [N] [--offset M]
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
- `N` — number of sessions to summarize in this batch (default 8; use a smaller number like 3–5 if the sessions are long or you want to keep token use low)
|
|
63
|
+
- `--offset M` — skip the first M sessions (use to process later batches)
|
|
64
|
+
|
|
65
|
+
Read the printed output carefully. Each block contains:
|
|
66
|
+
- `SESSION_ID` — the ID you must key the summary to
|
|
67
|
+
- `FIRST_PROMPT` / `COMPACT_SUMMARY` / `LAST_ASSISTANT` — context for writing the summary
|
|
68
|
+
- Project name, branch, cost, tools used, duration
|
|
69
|
+
|
|
70
|
+
### 4c. Write the summaries
|
|
71
|
+
|
|
72
|
+
For each session in the digest, write a **one- or two-sentence summary** that describes what the session accomplished. Be specific and factual — avoid generic phrases. Examples of good summaries:
|
|
73
|
+
|
|
74
|
+
- "Refactored auth middleware to fix session token storage; added integration tests."
|
|
75
|
+
- "Debugged a race condition in the job queue; traced to missing lock around queue.pop()."
|
|
76
|
+
- "Added CSV export to the billing report page and wired it to the existing API endpoint."
|
|
77
|
+
|
|
78
|
+
Produce a JSON object:
|
|
79
|
+
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"SESSION_ID_1": "Summary text here.",
|
|
83
|
+
"SESSION_ID_2": "Summary text here."
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### 4d. Apply the summaries
|
|
88
|
+
|
|
89
|
+
Pipe the JSON to `set_summaries.py`:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
echo '{"SESSION_ID_1": "...", "SESSION_ID_2": "..."}' | python scripts/set_summaries.py
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Or write it to a temp file and pass it:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
python scripts/set_summaries.py /tmp/summaries.json
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
The script prefixes each entry with `[Claude Summary]` (unless already present) and merges it into `data/session_summary.json`. It prints a confirmation line showing how many were merged.
|
|
102
|
+
|
|
103
|
+
### 4e. Refresh the dashboard
|
|
104
|
+
|
|
105
|
+
Tell the user to click **Refresh** in the dashboard header, or trigger it via the API:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
curl -s -X POST http://localhost:8042/api/refresh
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Summaries will now appear on the relevant session cards.
|
|
112
|
+
|
|
113
|
+
### 4f. Repeat for more batches (if needed)
|
|
114
|
+
|
|
115
|
+
The digest lists only sessions that are still **missing** a summary, so once a
|
|
116
|
+
batch is applied those sessions drop out of the list. To process the next
|
|
117
|
+
batch, run the same command again **without changing the offset**:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
python scripts/session_digest.py 8 # next batch — offset stays 0
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Do **not** increment `--offset` between applied batches — that would skip
|
|
124
|
+
sessions that still need summaries. Use `--offset` only to peek ahead at later
|
|
125
|
+
sessions without summarizing the earlier ones.
|
|
126
|
+
|
|
127
|
+
Ask the user after each batch whether to continue.
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## Notes
|
|
132
|
+
|
|
133
|
+
- You can stop summarizing at any time — summaries already written are saved.
|
|
134
|
+
- If `data/session_summary.json` does not exist yet, `set_summaries.py` creates it.
|
|
135
|
+
- To override the summary file location: `DASHBOARD_SUMMARY_FILE=/path/to/file python scripts/set_summaries.py ...`
|
|
136
|
+
- The dashboard never modifies `~/.claude/projects/` — all writes go to `data/`.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our Pledge
|
|
4
|
+
|
|
5
|
+
We as members, contributors, and maintainers pledge to make participation in
|
|
6
|
+
this project a harassment-free experience for everyone, regardless of age,
|
|
7
|
+
body size, visible or invisible disability, ethnicity, sex characteristics,
|
|
8
|
+
gender identity and expression, level of experience, education, socio-economic
|
|
9
|
+
status, nationality, personal appearance, race, religion, or sexual identity
|
|
10
|
+
and orientation.
|
|
11
|
+
|
|
12
|
+
## Our Standards
|
|
13
|
+
|
|
14
|
+
Examples of behavior that contributes to a positive environment:
|
|
15
|
+
|
|
16
|
+
- Being respectful of differing opinions, viewpoints, and experiences
|
|
17
|
+
- Giving and gracefully accepting constructive feedback
|
|
18
|
+
- Focusing on what is best for the community and the project
|
|
19
|
+
- Showing empathy toward other community members
|
|
20
|
+
|
|
21
|
+
Examples of unacceptable behavior:
|
|
22
|
+
|
|
23
|
+
- The use of sexualized language or imagery, and unwelcome sexual attention
|
|
24
|
+
- Trolling, insulting or derogatory comments, and personal or political attacks
|
|
25
|
+
- Public or private harassment
|
|
26
|
+
- Publishing others' private information without explicit permission
|
|
27
|
+
- Other conduct which could reasonably be considered inappropriate in a
|
|
28
|
+
professional setting
|
|
29
|
+
|
|
30
|
+
## Enforcement
|
|
31
|
+
|
|
32
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
|
33
|
+
reported by opening a GitHub issue or contacting the maintainers via the
|
|
34
|
+
repository. All complaints will be reviewed and investigated promptly and
|
|
35
|
+
fairly. Maintainers are obligated to respect the privacy and security of the
|
|
36
|
+
reporter of any incident.
|
|
37
|
+
|
|
38
|
+
Maintainers who do not follow or enforce the Code of Conduct may face
|
|
39
|
+
temporary or permanent repercussions as determined by the project leadership.
|
|
40
|
+
|
|
41
|
+
## Attribution
|
|
42
|
+
|
|
43
|
+
This Code of Conduct is adapted from the
|
|
44
|
+
[Contributor Covenant](https://www.contributor-covenant.org), version 2.1,
|
|
45
|
+
available at
|
|
46
|
+
<https://www.contributor-covenant.org/version/2/1/code_of_conduct.html>.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Bug reports, docs fixes, and code changes are all welcome.
|
|
4
|
+
|
|
5
|
+
## Getting started
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
uv sync --all-groups # runtime + dev tools (pytest, ruff) + security (bandit)
|
|
9
|
+
uv run python -m claude_dashboard # http://localhost:8042
|
|
10
|
+
uv run --group dev pytest -v # run the tests
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
> A plain `uv sync` installs runtime dependencies only (so end users who just want
|
|
14
|
+
> to run the dashboard stay lean). Contributors need `--all-groups` to get the test,
|
|
15
|
+
> lint, and security tooling.
|
|
16
|
+
|
|
17
|
+
## Guidelines
|
|
18
|
+
|
|
19
|
+
- **Stay local-first and read-only.** This tool must never modify a user's logs
|
|
20
|
+
or send data off their machine by default. Do not submit PRs that break this
|
|
21
|
+
rule without making it strictly opt-in.
|
|
22
|
+
- **No personal or sensitive data in commits.** Don't commit anything from
|
|
23
|
+
`data/`, `logs/`, `remote_public/`, or a real `scripts/deploy.env` — these are
|
|
24
|
+
gitignored. Use the synthetic fixtures in `tests/fixtures/` for tests.
|
|
25
|
+
- **Match the surrounding style.** The code favors small, dependency-light,
|
|
26
|
+
readable modules. The UI is intentionally vanilla JS + Chart.js — no build step.
|
|
27
|
+
- **Add tests** for parsing and pricing changes; those are the parts most likely
|
|
28
|
+
to regress.
|
|
29
|
+
|
|
30
|
+
## Pull requests
|
|
31
|
+
|
|
32
|
+
1. Fork and create a feature branch.
|
|
33
|
+
2. Make your change, add/adjust tests, and run `uv run --group dev pytest`.
|
|
34
|
+
3. Open a PR describing the change and the motivation.
|
|
35
|
+
|
|
36
|
+
## Reporting bugs
|
|
37
|
+
|
|
38
|
+
Open an issue with steps to reproduce. If it involves parsing, a **redacted**
|
|
39
|
+
snippet of the relevant JSONL (with paths and prompt text removed) is very helpful.
|
|
40
|
+
|
|
41
|
+
By contributing, you agree that your contributions are licensed under the
|
|
42
|
+
project's [MIT License](LICENSE).
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 The dashboard-for-claude-code contributors
|
|
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.
|