|
| 1 | +# Contributing |
| 2 | + |
| 3 | +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. |
| 4 | + |
| 5 | +## Development setup |
| 6 | + |
| 7 | +### Prerequisites |
| 8 | + |
| 9 | +- **Python 3.12** (matches CI) |
| 10 | +- **Node 20+** (only if you change `static/js/` or run frontend unit tests) |
| 11 | + |
| 12 | +### Bootstrap (Windows PowerShell) |
| 13 | + |
| 14 | +```powershell |
| 15 | +git clone https://github.com/cppalliance/claude-code-chat-browser.git |
| 16 | +cd claude-code-chat-browser |
| 17 | +python -m venv .venv |
| 18 | +.\.venv\Scripts\Activate.ps1 |
| 19 | +pip install -r requirements-dev.txt |
| 20 | +``` |
| 21 | + |
| 22 | +### Bootstrap (macOS / Linux) |
| 23 | + |
| 24 | +```bash |
| 25 | +git clone https://github.com/cppalliance/claude-code-chat-browser.git |
| 26 | +cd claude-code-chat-browser |
| 27 | +python -m venv .venv |
| 28 | +source .venv/bin/activate |
| 29 | +pip install -r requirements-dev.txt |
| 30 | +``` |
| 31 | + |
| 32 | +### Run the dev server |
| 33 | + |
| 34 | +```bash |
| 35 | +python app.py --port 5000 |
| 36 | +# Open http://127.0.0.1:5000 |
| 37 | +``` |
| 38 | + |
| 39 | +Useful flags: |
| 40 | + |
| 41 | +- `--base-dir PATH` — point at a different `projects/` tree (for tests or fixtures) |
| 42 | +- `--exclude-rules PATH` — session exclusion rules file |
| 43 | +- `--host 0.0.0.0` — listen on all interfaces (use only on trusted networks) |
| 44 | + |
| 45 | +## Running tests |
| 46 | + |
| 47 | +### Python |
| 48 | + |
| 49 | +```bash |
| 50 | +pytest -q # full suite + coverage (see pyproject.toml) |
| 51 | +pytest tests/test_api_integration.py -v |
| 52 | +pytest tests/test_search.py -v |
| 53 | +pytest tests/test_api_routes.py -v |
| 54 | +pytest tests/test_error_codes.py -v |
| 55 | +``` |
| 56 | + |
| 57 | +### JavaScript (vitest) |
| 58 | + |
| 59 | +Only needed when editing `static/js/`: |
| 60 | + |
| 61 | +```bash |
| 62 | +npm ci |
| 63 | +npm test |
| 64 | +npm run test:coverage # optional |
| 65 | +``` |
| 66 | + |
| 67 | +`node_modules/` is gitignored — run `npm ci` after clone. |
| 68 | + |
| 69 | +## Code style and conventions |
| 70 | + |
| 71 | +| Area | Convention | |
| 72 | +|------|------------| |
| 73 | +| **API errors** | Use `error_response()` from [`api/error_codes.py`](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`. | |
| 74 | +| **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). | |
| 75 | +| **Path safety** | Use `safe_join()` from `utils/session_path.py` for any path built from URL segments. | |
| 76 | +| **Imports** | stdlib → third-party → local, blank line between groups. | |
| 77 | +| **Line length** | ~100 characters; no enforced formatter yet. | |
| 78 | + |
| 79 | +## Tests required for common changes |
| 80 | + |
| 81 | +| Change | Add or update | |
| 82 | +|--------|----------------| |
| 83 | +| New HTTP route | Happy + error path in `tests/test_api_routes.py` or `tests/test_api_integration.py` | |
| 84 | +| New `ErrorCode` | Parametrized row in `tests/test_error_codes.py` | |
| 85 | +| Search / limit validation | `tests/test_search.py` | |
| 86 | +| New `_parse_tool_result` dispatch entry | Fixture + assertion in `tests/test_jsonl_parser.py` | |
| 87 | +| CLI behavior | `tests/test_cli_e2e.py` (subprocess) or `tests/test_cli_args.py` (parser only) | |
| 88 | +| Frontend shared module | `static/js/shared/*.test.js` (vitest) | |
| 89 | +| Error response shape | `tests/test_error_propagation.py` regression | |
| 90 | + |
| 91 | +## Branching and pull requests |
| 92 | + |
| 93 | +- Default branch: **`master`**. Do not push directly to `master`. |
| 94 | +- Branch names: `feat/<topic>`, `fix/<topic>`, `test/<topic>`, `chore/<topic>`, `docs/<topic>`. |
| 95 | +- One logical change per PR when possible. |
| 96 | +- PR checklist: |
| 97 | + - [ ] `pytest -q` green locally |
| 98 | + - [ ] `npm test` green if JS changed |
| 99 | + - [ ] CI jobs green (`pytest`, `integration-tests`, `js-tests`, `prod-install-smoke`) |
| 100 | + - [ ] PR description includes a **Test plan** section |
| 101 | + - [ ] API changes update [`docs/api-reference.md`](docs/api-reference.md) if behavior or errors change |
| 102 | + |
| 103 | +## Where things live |
| 104 | + |
| 105 | +| Task | Location | |
| 106 | +|------|----------| |
| 107 | +| Add HTTP route | `api/<area>.py`, register blueprint in [`app.py`](app.py) | |
| 108 | +| Add stable error code | [`api/error_codes.py`](api/error_codes.py) | |
| 109 | +| Parse JSONL / tool results | [`utils/jsonl_parser.py`](utils/jsonl_parser.py) — see [dispatch table notes](docs/architecture.md#dispatch-table) | |
| 110 | +| Project/session discovery | [`utils/session_path.py`](utils/session_path.py) | |
| 111 | +| Session statistics | [`utils/session_stats.py`](utils/session_stats.py) | |
| 112 | +| Bulk / per-session export | [`api/export_api.py`](api/export_api.py), [`utils/md_exporter.py`](utils/md_exporter.py) | |
| 113 | +| Export state on disk | [`utils/export_state_store.py`](utils/export_state_store.py) | |
| 114 | +| Exclusion rules | [`utils/exclusion_rules.py`](utils/exclusion_rules.py) | |
| 115 | +| CLI export | [`scripts/export.py`](scripts/export.py) | |
| 116 | +| SPA shell + routing | [`static/index.html`](static/index.html), [`static/js/app.js`](static/js/app.js) | |
| 117 | +| Shared frontend utilities | [`static/js/shared/`](static/js/shared/) | |
| 118 | +| API documentation | [`docs/api-reference.md`](docs/api-reference.md) | |
| 119 | + |
| 120 | +## Architecture |
| 121 | + |
| 122 | +See [`docs/architecture.md`](docs/architecture.md) for data flow, export state machine, and component diagram. |
| 123 | + |
| 124 | +## Getting help |
| 125 | + |
| 126 | +Open an issue with a clear repro or propose a draft PR early for CI feedback. |
0 commit comments