Initial scaffold
This commit is contained in:
commit
c6d8e902f6
3 changed files with 122 additions and 0 deletions
49
.gitignore
vendored
Normal file
49
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
# Secrets — never commit
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
*.pem
|
||||
*.key
|
||||
*.p12
|
||||
*.pfx
|
||||
secrets/
|
||||
credentials/
|
||||
.aws/
|
||||
.ssh/
|
||||
|
||||
# Dependencies / build artifacts
|
||||
node_modules/
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
.venv/
|
||||
venv/
|
||||
env/
|
||||
dist/
|
||||
build/
|
||||
target/
|
||||
*.egg-info/
|
||||
|
||||
# Editor / OS noise
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
|
||||
# Logs / caches
|
||||
*.log
|
||||
.cache/
|
||||
.pytest_cache/
|
||||
.mypy_cache/
|
||||
.ruff_cache/
|
||||
coverage/
|
||||
.coverage
|
||||
.nyc_output/
|
||||
|
||||
# Tauri / Vite
|
||||
src-tauri/gen/
|
||||
src-tauri/target/
|
||||
src-tauri/Cargo.lock
|
||||
*.tsbuildinfo
|
||||
.vite/
|
||||
30
CLAUDE.md
Normal file
30
CLAUDE.md
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
# Project: claude-usage-widget
|
||||
|
||||
A small always-on-top Windows desktop widget that visualizes local Claude Code usage — current 5-hour session block, 7-day rolling weekly window, and per-model token breakdown. Reads `~/.claude/projects/**/*.jsonl` directly (via `\\wsl$\<distro>\…` from Windows). No Anthropic API. No auth.
|
||||
|
||||
## Working agreement
|
||||
|
||||
- This is a git repo. Commit after each logical change with a one-line imperative message.
|
||||
- Read `memory.md` at session start. Update it before ending the session.
|
||||
- Never commit secrets — see `.gitignore` and the rules in `~/claude/CLAUDE.md`.
|
||||
|
||||
## Project-specific notes
|
||||
|
||||
- **Stack:** Tauri 2 (Rust + Svelte 5 + Vite + TS). Inline SVG for charts, no chart library.
|
||||
- **Build target:** Windows `.exe` only. Develop the Rust + frontend code in WSL; do `pnpm tauri dev` / `pnpm tauri build` on the Windows host (it needs MSVC toolchain + WebView2).
|
||||
- **Data source:** `~/.claude/projects/**/*.jsonl` — assistant lines have `message.usage.{input_tokens, output_tokens, cache_creation_input_tokens, cache_read_input_tokens}` and a `requestId` / `uuid` for dedupe (subagent transcripts in `<sessionId>/subagents/<id>.jsonl` overlap the parent).
|
||||
- **Aggregation algorithm:** ccusage-equivalent. 5-hour blocks are `floor_to_hour(first_ts) → +5h`; new block on ≥5h gap or when previous block ends. Weekly is rolling 7 days.
|
||||
- **Plan reference:** `~/.claude/plans/snug-mapping-milner.md` (the approved plan that drove this scaffold).
|
||||
|
||||
## Run
|
||||
|
||||
```powershell
|
||||
# On the Windows host, from this directory:
|
||||
pnpm install
|
||||
pnpm tauri dev # iterate
|
||||
pnpm tauri build # NSIS installer in src-tauri/target/release/bundle/nsis/
|
||||
```
|
||||
|
||||
## Verify
|
||||
|
||||
See `memory.md` and the plan file for the 10-step verification checklist (parse correctness, block boundary, dedupe, live tail, watcher fallback, autostart, etc).
|
||||
43
memory.md
Normal file
43
memory.md
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
# memory — claude-usage-widget
|
||||
|
||||
Durable memory for this project. Read at session start, update before session end. Date format: `YYYY-MM-DD`.
|
||||
|
||||
## Decisions & rationale
|
||||
|
||||
- **Tauri 2 (Rust + Svelte 5 + Vite + TS)** over Electron — smaller binary (~10 MB vs ~150 MB), native Windows transparency, real always-on-top z-order. Chose Svelte over React because the widget has only three SVG primitives; React boilerplate isn't worth it.
|
||||
- **Inline SVG, no chart library** — `BlockRing` is one circle, `WeeklyBar` is seven `<rect>`s, `ModelStack` is a stacked single-row bar. Adding Chart.js / ECharts / uPlot for ~80 lines of SVG would balloon the bundle for nothing.
|
||||
- **JSONL-only data source, no Anthropic API** — Anthropic doesn't expose a local cap-state file, but the JSONL transcripts contain everything we need to derive usage (this is what `ccusage` does). Avoids needing an admin key and keeps the widget fully offline.
|
||||
- **Widget runs on Windows host, not in WSLg** — needs to pin to the Windows desktop, autostart on login, and share the always-on-top z-order with native Windows apps. WSLg windows can't do that. The widget reads WSL transcripts via the `\\wsl$\<distro>\home\<user>\.claude\projects\` UNC mount.
|
||||
- **`notify` watcher + 60s tokio poll fallback** — `ReadDirectoryChangesW` on the WSL 9P mount is unreliable; the poll backstops it. 60 s is a pragmatic balance vs CPU.
|
||||
- **All filesystem reads happen Rust-side** — the JS `capabilities/default.json` does NOT grant `tauri-plugin-fs`. Keeps the webview sandbox tight.
|
||||
- **Block algorithm** — `block_start = floor_to_hour(first_ts_of_block)`, `block_end = block_start + 5h`, new block on ≥5h gap OR when previous block ends. This matches ccusage and the way Anthropic's docs describe the rolling window.
|
||||
- **Weekly = rolling 7 days, no calendar anchoring** — Anthropic's reported Max-plan weekly reset day is buggy and shifts (see GH issues #54974, #52921). The honest thing is "past 7 days from now."
|
||||
- **Caps are user-configurable in Settings** with placeholder defaults (200k tokens / 5h block, 2M tokens / week). No authoritative local source for the real caps.
|
||||
|
||||
## Open questions / TODOs
|
||||
|
||||
- [ ] Tune cap defaults once we have a few weeks of real data — current 200k / 2M values are guesses.
|
||||
- [ ] Decide whether to expose a tray icon for relaunch after `quit_app` (currently the widget can only be reopened via Start Menu / autostart).
|
||||
- [ ] Consider whether to fold in the pricing / `$ estimate` view later — out of scope for v0 per user.
|
||||
- [ ] Verify subagent dedupe assumption: do subagent JSONLs ever contain assistant lines that aren't also in the parent transcript? If yes, we MUST count them; if always duplicate, we MUST skip them. Plan currently uses `requestId || uuid` set, which is safe either way.
|
||||
- [ ] Replace placeholder Tauri icons in `src-tauri/icons/` before release.
|
||||
|
||||
## Session log
|
||||
|
||||
### 2026-05-08
|
||||
- Created project scaffold per the approved plan at `~/.claude/plans/snug-mapping-milner.md`.
|
||||
- Authored Tauri config (frameless, transparent, alwaysOnTop, skipTaskbar, 280×360), Cargo.toml, capabilities/default.json.
|
||||
- Authored Rust modules: `state.rs`, `settings.rs`, `paths.rs`, `jsonl.rs`, `usage.rs`, `watch.rs`, `commands.rs`, `lib.rs`, `main.rs`.
|
||||
- Authored Svelte frontend: `App`, `TitleBar`, `BlockRing`, `WeeklyBar`, `ModelStack`, `Settings` components plus `ipc.ts`, `types.ts`, `format.ts`.
|
||||
- Wrote `scripts/seed-fake-jsonl.ps1` verification helper and `README.md` build instructions.
|
||||
- Toolchain (rust/node/pnpm) NOT installed in this WSL environment — that's expected; the build runs on the Windows host. `cargo check` / `pnpm install` not yet run.
|
||||
|
||||
## External references
|
||||
|
||||
- Approved plan: `/home/megaproxy/.claude/plans/snug-mapping-milner.md`
|
||||
- Tauri 2 prerequisites: https://v2.tauri.app/start/prerequisites/
|
||||
- Tauri 2 window customization: https://v2.tauri.app/learn/window-customization/
|
||||
- Tauri 2 autostart plugin: https://v2.tauri.app/plugin/autostart/
|
||||
- Tauri 2 capabilities: https://v2.tauri.app/security/capabilities/
|
||||
- ccusage (algorithm reference): https://github.com/ryoppippi/ccusage
|
||||
- Claude Max weekly reset issues (context for "rolling 7d" choice): https://github.com/anthropics/claude-code/issues/54974 · https://github.com/anthropics/claude-code/issues/52921
|
||||
Loading…
Add table
Add a link
Reference in a new issue