Thanks for considering a patch. This repo is a small Flask app plus a hash-routed SPA and a CLI export script. Keep changes focused and tested.
- Python 3.12 (matches CI)
- Node 20+ (only if you change
static/js/or run frontend unit tests)
CI runs ruff check, ruff format --check, pip-audit, pytest, integration tests, and Vitest on Ubuntu, Windows, and macOS (ubuntu-latest, windows-latest, macos-latest; Python 3.12, Node 20). Type-check (mypy) and production install smoke run on Ubuntu only.
git clone https://github.com/cppalliance/claude-code-chat-browser.git
cd claude-code-chat-browser
python -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -r requirements-dev.txtgit clone https://github.com/cppalliance/claude-code-chat-browser.git
cd claude-code-chat-browser
python -m venv .venv
source .venv/bin/activate
pip install -r requirements-dev.txtpython app.py --port 5000
# Open http://127.0.0.1:5000Useful flags:
--base-dir PATH— point at a differentprojects/tree (for tests or fixtures)--exclude-rules PATH— session exclusion rules file--host 0.0.0.0— listen on all interfaces (use only on trusted networks; never with--debug)--debug— Flask/Werkzeug debug mode (loopback hosts only; enforced when starting viapython app.py, notflask runor WSGI). Extending the guard toFLASK_DEBUG/flask runis a planned follow-up.
- CHANGELOG.md — user-visible changes per release
- docs/deprecation-policy.md — how deprecated API fields are removed
- docs/api-reference.md — field stability (
stable/experimental/deprecated)
When changing JSON response shapes, update the API reference stability column and CHANGELOG before removing fields.
ruff check . # lint (E, F, W, I) — same gate as CI
ruff format --check . # formatting gate; run `ruff format .` to fix
pip-audit -r requirements.txt # production dependency audit (CI gate)
pytest -q # full suite + coverage (see pyproject.toml)
pytest tests/test_api_integration.py -v
pytest tests/test_search.py -v
pytest tests/test_api_routes.py -v
pytest tests/test_error_codes.py -v
pytest tests/benchmarks/ --benchmark-only -o addopts= -v # performance baselines (see benchmarks/README.md)Only needed when editing static/js/:
npm ci
npm test
npm run test:coverage # optionalnode_modules/ is gitignored — run npm ci after clone.
| Area | Convention |
|---|---|
| API errors | Use error_response() from api/error_codes.py. Do not call jsonify({"error": ...}) without a code field. Add new members to ErrorCode and a row in tests/test_error_codes.py. |
| Exception leakage | 5xx bodies are generic messages only. Log full tracebacks with current_app.logger.exception(...). Never put str(e) or class names in HTTP JSON (issue #25). |
| Path safety | Use safe_join() from utils/session_path.py for any path built from URL segments. |
| Imports | stdlib → third-party → local, blank line between groups. |
| Lint / format | ruff check . and ruff format --check . (CI gates). Config in pyproject.toml; run ruff format . to apply formatting locally. |
| Line length | 100 characters (line-length in pyproject.toml). |
| Change | Add or update |
|---|---|
| New HTTP route | Happy + error path in tests/test_api_routes.py or tests/test_api_integration.py |
New ErrorCode |
Parametrized row in tests/test_error_codes.py |
| Search / limit validation | tests/test_search.py |
New _parse_tool_result dispatch entry |
Fixture + assertion in tests/test_jsonl_parser.py |
| New Claude Code tool use name | See Adding a new tool type below |
| CLI behavior | tests/test_cli_e2e.py (subprocess) or tests/test_cli_args.py (parser only) |
| Frontend shared module | static/js/shared/*.test.js (vitest) |
| Error response shape | tests/test_error_propagation.py regression |
- Default branch:
master. Do not push directly tomaster. - Branch names:
feat/<topic>,fix/<topic>,test/<topic>,chore/<topic>,docs/<topic>. - One logical change per PR when possible.
- PR checklist:
-
ruff check .andruff format --check .green locally -
pytest -qgreen locally -
npm testgreen if JS changed - CI jobs green (
lint-and-audit,pytest,integration-tests,js-testson Ubuntu + Windows + macOS;mypy,prod-install-smokeon Ubuntu) - PR description includes a Test plan section
- API changes update
docs/api-reference.mdif behavior or errors change
-
| Task | Location |
|---|---|
| Add HTTP route | api/<area>.py, register blueprint in app.py |
| Add stable error code | api/error_codes.py |
| Parse JSONL / tool results | utils/jsonl_parser.py — see dispatch table notes |
| Project/session discovery | utils/session_path.py |
| Session statistics | utils/session_stats.py |
| Bulk / per-session export | api/export_api.py, utils/md_exporter.py |
| Export state on disk | utils/export_state_store.py |
| Exclusion rules | utils/exclusion_rules.py |
| CLI export | scripts/export.py |
| SPA shell + routing | static/index.html, static/js/app.js |
| Shared frontend utilities | static/js/shared/ |
| API documentation | docs/api-reference.md |
| Deprecation policy | docs/deprecation-policy.md |
| Changelog | CHANGELOG.md |
See docs/architecture.md for data flow, export state machine, and component diagram.
Claude Code assistant tool_use blocks carry a name string (e.g. "Read", "Bash"). The browser coordinates that name across four sites; drift is caught by tests/test_tool_dispatch_sync.py.
utils/tool_dispatch.py— add the name to_FILE_ACTIVITY_HANDLERS(Noneif no file/bash/web side effects);KNOWN_TOOL_TYPESis derived from its keys. If the tool has a distincttoolUseResultJSON shape, add(predicate, builder)to_TOOL_RESULT_DISPATCH(respect ordering — see module docstring andtests/test_tool_dispatch_ordering.py).models/tool_results.py— add the name toToolNameLiteraland, when the tool has a distinct result payload, add the TypedDict, type guard (is_*_tool_result), and union member onToolResultUnion.utils/md_exporter.py— add anelif name == "…"branch in_render_tool_use(sync test parses these branches).static/js/render/registry.js— add aTOOL_USE_RENDERERSentry (and atool_use/*.jsrenderer module).- Regenerate
static/tool_types.json:python scripts/gen_tool_types_manifest.py - Optional result UI — if the backend emits a new
result_type, addTOOL_RESULT_RENDERERSand atool_result/*.jsmodule. - Run
pytest tests/test_tool_dispatch_sync.py -v— failure names the site missing the new type.
Open an issue with a clear repro or propose a draft PR early for CI feedback.