CLAUDE.md · git:20261022.0479ade · 2026-10-22 · sha256 c2af278409cb305a
CLAUDE.md git:20261022.0479adeA
Immutable. This exact content never changes and is served at /api/v1/blob/c2af278409cb305a.
# Working in this repo House rules for Claude Code. Long-form rationale, tables, and incident notes: `docs/agent-rules.md`. User-facing docs: `README.md`, `CONTRIBUTING.md`. ## Public OSS Everything ships to github.com/amirfish1/claude-command-center. - No internal paths, client names, private URLs, PII, or real-looking secrets (use `sk-ant-test-XXXX`). - Private plans/specs/backlog/agent working docs live in the private `CCC-private-docs` repo. Never recreate `docs/superpowers/`, copy private docs here, or link that repo in. - The Morning view (`morning.py`, `morning_store.py`, `static/morning/`) is a gitignored personal plugin; keep it out of README/core. ## Commits - Conventional Commits; match scopes in `git log` (`fix(layout)`, `feat(ui)`, `docs`, `chore`, `perf`). Subject ≤70 chars, body says why. - Stage by path; commit with `git commit --only <paths> -m "..."`. Never `git add -A`/`.`/`commit -a`. - Ask before `git checkout -- .`, `git restore .`, `git clean -f`, `git reset --hard`. Never force-push `main`; never `--no-verify` past `scripts/pre-push.sh`. - Commit means push: `git push origin main`, then confirm `git rev-parse HEAD` == `git ls-remote origin refs/heads/main`. - If a gitignored `CLAUDE.local.md` exists, read and follow it (it overrides this section). - User-visible change → add `changelog.d/<category>-<slug>-<date>.md` (bullet text only; categories added/changed/fixed/removed/security/deprecated). Never edit `CHANGELOG.md` directly. - Releases: `./scripts/cut-release.sh X.Y.Z` (`--dry-run` first); see `docs/RELEASING.md`. Version lives in `pyproject.toml` and `server.py` `__version__`. - What needs a deploy beyond push (`scripts/macapp/`, DMG, Sparkle, `infra/telemetry-worker/`, Homebrew): `docs/agent-rules.md`. ## API and security - `/api/*` is public API: adding fields/endpoints is fine; renaming/removing/reshaping is a major bump. - Read `SECURITY.md` before touching binding, origin checks, or path validation. Don't loosen the `/api/repo/switch` allow-list. ## Conventions - `server.py` is stdlib-only (no pip deps at runtime). `static/index.html` is a single-file app (no bundler/npm). - `hooks/` scripts run in Claude Code's hook pipeline: exit fast, never prompt. - Bounding headless `claude -p` to read-only tools needs `--disallowedTools` too; `--allowedTools` alone doesn't restrict. - Fix UI staleness at its source (auto-refresh); never add a manual refresh button. - Never hold a foreground Bash polling loop for more than minutes; use `run_in_background`, Monitor, or end the turn (a live turn blocks queued input). ## Performance gates Every "CCC is slow" incident was O(all sessions) work per item, uncached. On any path scanning `~/.claude/projects` or session state: gate live work by candidacy, cache by `(mtime, size)` persisted to disk, never spawn a subprocess per row, skip flags the view doesn't render. `tests/test_perf_budget.py` (run by the pre-push gate) enforces call counts; add a test for any new all-sessions path; never relax a bound. ## Credential requests When a task needs a credential, use the [credential broker](docs/credential-broker.md) to show a masked dashboard prompt instead of asking for the value in chat or asking the user to SSH in. Default: `ccc secret request NAME --reason "..."` saves the value to the CCC Vault and prints only the entry name; then use it with `ccc vault exec --env VAR=NAME -- cmd`. Only when a program must receive the value directly, pipe `ccc secret request NAME --reason "..." --return-key` into a program that accepts credentials on stdin; never let a tool capture the value into a transcript. Keep names/reasons free of secrets. It requires explicit consumer integration; it does not intercept login prompts automatically. ## Testing - Run targeted tests locally: `python3 -m pytest tests/test_<feature>.py`. Never run `tests/test_smoke.py` locally (>4 GB RAM, freezes the server); CI runs it. - Full unittest run: `PYTHONWARNINGS="ignore::ResourceWarning" python3 -m unittest discover`. - Don't mock `gh`/`claude`/`pkood` in unit tests. - UI checks: `node snapshot.js` (puppeteer 25, no `page.waitForTimeout`) or the chrome-devtools MCP. Never Playwright.