Thank you for your interest in contributing.
-
Fork and clone the repository.
-
Copy
.env.exampleto.env. -
Start the full stack:
docker compose pull docker compose up -d
Or build from source:
docker compose -f docker-compose.yml -f docker-compose.dev.yml up --build -
Open the UI at http://localhost:3001 and the API at http://localhost:8080.
-
Optional — enable passkey auth: see Authentication in the README (
docker compose run --rm api auth bootstrap-admin).
- API:
go run ./main.gowithDATABASE_URLandBROWSER_WS_URLset. - Frontend:
cd frontend && npm install && npm run devwithNEXT_PUBLIC_API_URL=http://localhost:8080in.env.local.
dev— integration branch for features and fixes.main— stable releases only.- Branch from
devfor all contributions.
-
Create a feature branch from
dev. -
Make changes with tests where applicable.
-
If you add a dependency, gatherer, API route, or worker, update appmap.md and THIRD_PARTY.md as appropriate.
-
Verify locally:
go test $(go list ./... | grep -v '/frontend/') cd frontend && npm run typecheck && npm run build cd frontend && npm run test:e2e
E2E boots the Docker Compose stack (see
frontend/e2e/global-setup.ts), bootstraps or issues a recovery code, registers a virtual passkey, then runs smoke, auth, delete, and report specs. Local runs preservepostgres_dataon the default compose project; CI usesE2E_COMPOSE_PROJECT=echostate-e2ewith fresh volumes. -
Open a pull request targeting
dev. -
After review, changes merge to
devand are promoted tomainfor release.
gofmtandgo vetbefore committing.- Keep handlers thin; business logic lives in
internal/packages. - Recon gatherers should fail gracefully — partial results are valuable.
- TypeScript strict mode; match existing shadcn/ui patterns.
- Use
data-testidon interactive elements targeted by Playwright. - Run
npm run formatif you touch TSX files.
- Use Conventional Commits (
feat:,fix:,docs:,chore:,test:, etc.). - Write concise, natural messages — not robotic filler.
- A short Scooby-Doo quote at the end is optional project tradition.
The canonical version lives in the root VERSION file. Before tagging, bump that file and sync the frontend manifest:
echo "0.0.1-beta.10" > VERSION
./scripts/sync-version.shReleases are tagged on main (or dev for betas) with a v prefix, e.g. v0.0.1-beta.10.
git tag -a v0.0.1-beta.10 -m "v0.0.1-beta.10"
git push origin v0.0.1-beta.10Tag pushes trigger GitHub Release binaries and GHCR image builds via Actions.
Update TODO.md and CHANGELOG.md when completing roadmap items or shipping user-facing changes.