# Contributing to claudestat Thanks for your interest in contributing. claudestat is a small, focused tool — contributions that keep it lean and reliable are always welcome. --- ## Ways to contribute - **Bug fix** — something breaks or behaves unexpectedly - **New pattern** — add a usage insight to the pattern analyzer - **Dashboard improvement** — new chart, better UX, accessibility fix - **New command** — extend the CLI with useful functionality - **Documentation** — fix a typo, clarify a step, add an example If you're unsure whether your idea fits, open an issue first and describe what you want to build. --- ## Setup **Requirements:** Node.js >= 22, Claude Code installed locally. ```bash # 1. Fork the repo on GitHub, then clone your fork git clone https://github.com/YOUR_USERNAME/claudestat cd claudestat # 2. Install backend dependencies npm install # 3. Install dashboard dependencies cd dashboard && npm install && cd .. # 4. Run in dev mode npm run dev:full # starts daemon + dashboard hot-reload together # or separately: # npm run dev # daemon only (tsx, no build needed) # cd dashboard && npm run dev # dashboard Vite dev server # 5. Run the test suite npm test ``` The dashboard dev server runs at `http://localhost:5173` (Vite). The daemon listens for hook events and serves the API at `http://localhost:7337`. --- ## Project structure ``` claudestat/ ├── src/ # Backend — daemon, CLI, DB, analytics │ ├── index.ts # CLI entry point (commander) │ ├── daemon.ts # Express server + event loop │ ├── db.ts # SQLite operations (node:sqlite) │ ├── intelligence.ts # Loop detection, pattern analysis, weekly insights │ ├── insights.ts # Usage insights and recommendations │ ├── enricher.ts # Correlates hook events with JSONL token data │ ├── notifier.ts # Webhook + desktop notifications │ ├── export.ts # Data export (JSON, markdown, CSV) │ ├── logger.ts # Structured logging with log levels │ ├── install.ts # Hook installer / uninstaller │ ├── config.ts # Config read/write/validate │ ├── paths.ts # Resolved paths for data, hooks, logs │ ├── service.ts # System service management (launchd/systemd) │ └── routes/ # Express route handlers │ ├── projects.ts │ ├── helpers.ts │ └── misc.ts ├── dashboard/ # Frontend — React + Vite + Recharts │ └── src/ │ └── components/ # One file per view/component ├── hooks/ │ └── event.js # Hook script copied to ~/.claudestat/hooks/ ├── tests/ │ ├── index.ts # Test entry point — registers all test files │ ├── db.test.ts # DB integration tests (in-memory SQLite) │ ├── intelligence.test.ts │ ├── config.test.ts │ ├── export.test.ts │ ├── helpers.test.ts │ └── ... # 25+ test files total └── package.json ``` --- ## Making changes ### Branch naming ``` fix/description-of-bug feat/name-of-feature docs/what-you-changed refactor/what-you-simplified ``` ### Code style - TypeScript strict mode — no `any` unless necessary - Keep functions small and focused - No external dependencies unless clearly justified — the backend has zero runtime deps beyond `express`, `chokidar`, and `commander` - Dashboard uses React 19 patterns (no class components, no legacy context) ### Adding a pattern to the analyzer Open `src/intelligence.ts` or `src/insights.ts`. Each pattern is a self-contained block that returns or pushes to the insights array. Follow the existing structure: ```typescript // 1. Compute the metric const myRatio = someCount / total // 2. Check the threshold if (myRatio >= THRESHOLD) { insights.push({ title: 'Short descriptive title', description: 'One sentence explaining why this matters and what to do.', level: 'tip' | 'warning' | 'positive', metric: `${(myRatio * 100).toFixed(0)}%`, }) } ``` Then add a test in `tests/intelligence.test.ts` covering at least: triggered case, non-triggered case, and any edge case (e.g. division by zero). --- ## Tests All tests use `node:test` (built-in, zero extra deps) with `tsx/cjs` for TypeScript transpilation. ```bash npm test ``` Expected output: **271 tests passing** (as of v1.8.0). All tests must pass before opening a PR. - `tests/db.test.ts` — integration tests against an in-memory SQLite DB - `tests/intelligence.test.ts` — loop detection, pattern analysis - `tests/config.test.ts` — config validation - `tests/export.test.ts` — export formats and file output - `tests/helpers.test.ts` — `findGitRoot`, `findProjectCwdForFile` If you add a new `dbOps` function, add a test in `db.test.ts`. If you modify `intelligence.ts`, add a test in `tests/intelligence.test.ts`. --- ## Opening a PR 1. Make sure `npm test` passes locally 2. Make sure `npm run build` completes without errors 3. Open a PR against the `main` branch 4. Include in the PR description: - **What** changed - **Why** it was needed - **How** to test it manually (if not fully covered by automated tests) Keep PRs focused. One feature or fix per PR — easier to review and merge. --- ## Reporting a bug Open an issue and include: - Node.js version (`node --version`) - OS and version - Steps to reproduce - What you expected vs what happened - Any relevant output from `claudestat status` or the terminal --- ## Questions Ask in [GitHub Discussions](https://github.com/DeibyGS/claudestat/discussions) — no question is too small.