| title | Contribution Guide |
|---|---|
| icon | code-pull-request |
| description | Contribute to Omi and earn rewards! Some tasks have paid bounties. |
Before you write code, check product fit:
- Read
PRODUCT.md— memory-first loop, one shared chat mind, trust over cleverness, integrations harness, taste floor. - Check the product invariant registry. Locked invariants (for example one shared transcript across notch and main chat) are binding; PRs that touch their paths must name the invariant ID.
- Large or ambiguous features should start as a GitHub issue so maintainers can align on scope and direction before major implementation work begins.
Maintainers declining a PR for direction or taste will cite an invariant ID or open a proposed invariant the same week — so “project direction” stays written down, not tribal.
Go to [github.com/BasedHardware/Omi](https://github.com/BasedHardware/Omi) and click **Fork**. Clone your fork, create a branch, and implement your changes. Add focused tests and include the commands or manual steps you used to verify the change. Before pushing, draft the PR body and run `make preflight`, then run `scripts/pr-preflight --pr-body-file /path/to/draft-pr-body.md` to validate invariant citations and any required failure-class declaration. Use `scripts/pr-preflight --suggest` before drafting the body to get the paste-ready invariant section and failure-class guidance. The manifest-backed checks are identical locally and in CI. Submit a PR and specify which issue it relates to. Name any product invariants your change affects.
The capture ownership contract
defines constructor seams, session generations and staged recovery/foreground
ownership handoffs. Declare completed file/rule adoption in
app/contracts/capture/boundary-baseline.json. Only adopted files and new files
are constrained; ordinary legacy-file growth stays unblocked. Diagnostics name
the request interface to use. Run TZ=UTC bash app/test.sh for the protected contracts. Pending tests
execute and fail on unexpected success; builders remove only their pending marker.
For native BLE changes, distinguish a connected radio from device audio setup. The device lifecycle architecture describes late readiness after a launch timeout and the Limitless regression path.
Good PRs are easy to review and come with evidence that the change works.
- Bug fixes include the regression test that would have caught the bug.
- Classify reactive fixes. A
fix:commit responds to a triggering defect and must declareFailure-Class: FC-<slug> | new | nonein its PR body. Aharden:commit strengthens a boundary or contract without a triggering incident; it may cite a class but needs no declaration. The validator is offline and required; itsreportcommand is advisory and only identifies classes eligible for a maintainer to markdormant. - Keep instance fixes compact. An existing-class declaration replaces the
root-cause and durable-guard narrative. Provide that extended narrative only
when declaring
new, changing a class's canonical prevention primitive or owner, or making a registry-only lifecycle transition. An instance-fix PR never edits registry data. To mark a class dormant, a separate registry-only PR setsstatustodormantwith a UTC ISO-8601dormant_since. Whenreportflags a recurrence after that timestamp, merge a separate registry-only reopen PR that setsstatustoopenand removesdormant_since, then classify the instance fix. IDs use stable semantic lower-kebab slugs such asFC-malformed-doc-read; usescripts/failure-class prepareorexplainfor the exact field and relevant context. - Prefer primitives to guards. Before adding a check or ratchet, answer in the PR body: “Why isn't this a shared primitive instead?” A new guard must cite the real merged PR or incident it would have caught; no real instance means the check does not land.
- Small features can go straight to PR when they are well scoped: test the core path and the main error path, and describe any manual verification you did.
- Large or ambiguous features should start as a GitHub issue so maintainers can align on scope and direction before major implementation work begins.
- Show your verification. List the commands you ran and what they showed in the PR description. "It compiles" is not evidence — exercising the real user-facing path is.
- Tests that run in CI must be hermetic — no live services, no network. Validation against a live service is welcome as extra evidence, but it can never be the only proof a PR works.
- CI on fork PRs — fork PRs run the cheap checks (Hygiene, Formatting, metadata, affected backend/Python units, Static Contracts, and OpenAPI). App PRs also run
Dart Analyze & Tests(the analyzer ratchet and regular Flutter tests), including forks withoutci:full.Mobile Release Eligibilityfails if selected Flutter coverage did not run and pass. Once maintainers require that status on main, app PRs cannot merge without passing Flutter coverage. Generated-file checks, iOS compile, Android compile and JVM tests, emulator acceptance, seeded journeys, slow backend guardrails, and the Windows Python ACL check still wait for full CI on fork PRs. When a contribution is ready for full review, ask a maintainer to add theci:fulllabel, then use Re-run all jobs on the PR's latest commit. CI reads the current labels on rerun; adding a label alone does not start new workflows or cancel an in-flight run. The label persists across new commits, which then get full CI automatically. Heavy aggregate checks name this flow when coverage is deferred. - Backend hermetic gate — every PR reports
Backend Hermetic Merge Gate. Affected full-tier PRs run the backend E2E harness; emulator gauntlets run for their integration inputs, main, and nightly. A cheap-tier fork reports deferral instead of a green heavy-check verdict. - Behavioral tests execute production behavior. Source-string assertions are static tripwires only; they do not prove lifecycle, concurrency, or integration behavior.
- Product invariants — if you touch paths listed on a locked invariant, name the ID (for example
INV-CHAT-1) in the PR body. - Fast local deterministic checks — run
make preflight. Selection includes staged, unstaged, and untracked files; commit-based checks still need a final run after committing. New deterministic diff-scoped checks belong in.github/checks-manifest.yaml, never directly in workflow YAML. - CI budget — when adding or changing a workflow or job, run
python3 .github/scripts/check_ci_budget.py --refresh, then review.github/ci-budget.yaml. Set a p50 runtime budget, expected PR runs per day, owner, and rationale for new jobs. A wider trigger, larger matrix, runner change, or raised budget needs an explicit budget and rationale edit in the same PR. After CI diet changes merge, re-seed measured fields with--refresh --reseed --seed-dayruns <dayruns.tsv> --seed-dayjobs <dayjobs.tsv>and review the diff. The checked-in caps cover PR Linux and macOS runner minutes per day and internal time-to-signal. The weekly audit samples completed PR runs withGITHUB_TOKEN, publishes a report artifact, and updates one tracking issue on overrun or insufficient samples. - PR metadata contract check — draft the body, then run
scripts/pr-preflight --pr-body-file /path/to/draft-pr-body.md. Usescripts/pr-preflight --suggestwhen you need the paste-ready invariant section. Once the branch has a PR,scripts/pr-preflightreads its current body automatically withgh(or setOMI_PR_BODY_FILE). Pre-push runs these same contracts. When editing only the PR body, usescripts/pr-preflight --metadata-only --pr-body-file /path/to/draft-pr-body.md. This runs every applicable metadata-dependent check and reports all failures together. CI uses this mode for title, body, and label edits; code updates still run the full preflight. Metadata success validates the PR description and does not replace the source-code verdict.
Backend compatibility checks cover adopted released-client shapes in
contracts/client-compat/. Preserve fields and request forms those clients use;
new unused endpoints stay unrestricted. A failure identifies the release and
field: restore compatibility or version the endpoint, rather than editing a
historical fixture. Replay uses synthetic records in the existing backend E2E
suite; a successful build tag alone is not proof of store distribution.
For typed mobile analytics, add events and executable consumer references to
contracts/analytics/events.json, then run
python3 scripts/check_event_registry.py --write and commit the generated Dart
API and tracking plan. Preserve emitted names and properties during migration.
The raw-call check covers adopted files; new and existing unadopted files stay
unrestricted. See app/lib/utils/analytics/registry/REGISTRY.md for batch tests.
Omi is built to be agent-friendly. If you use an AI coding agent, it will automatically pick up AGENTS.md at the repo root (plus per-component guides in backend/, app/, and desktop/macos/). The root guide routes to component instructions and repository conventions. The PR quality requirements above apply to all contributions; maintainer-machine instructions apply only when using those machines.
Docs contributions are just as important as code contributions! Our docs are located in the GitHub docs folder and sync in real-time with docs.omi.me.
You can edit docs directly from GitHub: Fork the repo → [click the edit icon](https://share.cleanshot.com/dkBSffGr) → click "Preview" → create a pull request.Get rewarded for approved PRs with significant contributions:
Free DevKit device (necklace or glasses, depending on contribution area) $100 of transcription credits $500 of transcription credits + special Contributor role in Discord Trip to hang out with the Based Hardware team Something you spent 5+ hours on. Can be multiple smaller contributions that add up. Either a new feature or a major bug fix. Quality code with clear explanations, focused tests, and verification notes. To claim your reward, email [team@basedhardware.com](mailto:team@basedhardware.com) with: - List of your contributions - Your address - Email and phone numberGet paid to improve AI wearables!
Browse open issues with the "Paid Bounty" label| Rule | Description |
|---|---|
| Code must be merged | Your code must be merged into the master branch |
| Eligibility | Bounty eligibility is solely at our discretion |
| Locking a task | You can "lock" a bounty task, but only after your first PR is merged |
| Claiming payment | Email team@basedhardware.com with bounty link + PayPal account |
If there are no paid bounties available, you can suggest your own:
Filter by [open issues](https://github.com/BasedHardware/Omi/issues?q=is:open+is:issue) without the "bounty" label. Comment on the issue and ping @josancamon19 or @kodjima33 with your bounty suggestion.Browse all open issues View issues with bounties Join the community Contribute to docs