Thanks for your interest in contributing! Neru is a small project with an approachable codebase, and we welcome contributions of all kinds — code, docs, bug reports, config examples, or ideas.
This document owns the contribution process: how to propose a change, how to commit it, and how to get it merged. The technical guides own the rest — DEVELOPMENT.md for environment setup, building, and testing; ARCHITECTURE.md for how the codebase is structured; CROSS_PLATFORM.md for platform work; and AGENTS.md for conventions and contracts.
- Code of Conduct
- Getting Started
- Making Changes
- Commit Messages
- Pull Requests
- Platform Work
- AI-Assisted Contributions
- Good First Contributions
- Reporting Bugs
- Feature Requests
This project follows our Code of Conduct. By participating you agree to uphold it. Please report unacceptable behavior privately by contacting @y3owk1n directly — not via public issues, so reports stay confidential.
- Search existing issues — check whether someone is already working on the same thing, or whether there's a related discussion.
- Open an issue first for non-trivial changes. This avoids wasted effort and lets us align on approach before you write code.
- Small, focused PRs are preferred over large, sweeping ones.
Set up your environment by following DEVELOPMENT.md — Devbox is the recommended path and provides every tool pre-configured.
-
Fork the repository and clone your fork.
-
Create a branch from
main:git checkout -b feat/my-feature
-
Make your changes, following the conventions in AGENTS.md. Where new code belongs is mapped out in DEVELOPMENT.md.
-
Add or update tests. All new code needs coverage — see DEVELOPMENT.md for the test tiers and AGENTS.md (Conventions) for naming, mocks, and build tags.
-
Run the pre-commit checks:
just fmt # format Go and Objective-C just lint # golangci-lint just test # unit + integration — see the warning below just build # verify the build
[!IMPORTANT] On macOS,
just testincludes integration tests that drive your real cursor, keyboard, and overlays, and they need Accessibility permission granted to your terminal (System Settings → Privacy & Security → Accessibility). Runjust test-unitif you only want the safe subset, and quit any runningnerudaemon first — a live daemon holding the socket makes the IPC integration tests silently skip. Details in DEVELOPMENT.md.Before pushing, run
just ci— it is exactly what CI gates your PR on, and it is a superset of the checks above (addsgo vet, the cross-platform foundation slice, a-racepass over the unit suite, the CI profile of the integration suite, and a vulnerability scan). For the deepest verification on a real desktop session,just test-allruns full integration under-racetoo. Doing Linux or Windows work? Start withjust test-foundationandjust build-linux/just build-windows. -
Update the docs in the same PR. Each fact has one home — the documentation checklist says which file owns what, so please update the owner rather than restating it in a second place.
On linters: the linter set is strict on purpose, and
//nolintis the escape hatch, not the default. Use one only when the finding is a genuine false positive or the compliant form would be clearly worse — always with the specific linter named and a trailing// reason. If you find yourself suppressing the same linter repeatedly, that linter may be wrong for this codebase: propose disabling it in.golangci.yml(with the reason recorded there) instead of scattering suppressions. -
Commit using conventional commits, then push and open a pull request.
We use Conventional Commits to power automated releases via Release Please. The commit subject is what ships in the changelog, so write it for users.
Format:
<type>(<optional scope>): <subject>
<optional body>
<optional footer>
Types:
| Type | When to use |
|---|---|
feat |
New feature |
fix |
Bug fix |
docs |
Documentation only |
style |
Formatting, no logic change |
refactor |
Code restructuring, no behavior change |
perf |
Performance improvement |
test |
Adding or updating tests |
chore |
Build, CI, dependencies, tooling |
Examples:
feat(grid): add recursive subdivision mode
fix(hints): correct overlay positioning on multi-monitor setups
docs: update configuration reference for scroll mode
A fuller message earns its body by explaining why:
feat: add grid-based navigation mode
Implement grid-based navigation as an alternative to hints. Grid mode divides
the screen into cells and allows precise cursor positioning without relying on
the accessibility tree.
Closes #123
- Title follows the same conventional commit format (e.g.
feat(hints): add multi-monitor support). - Description explains what changed and why. Include screenshots or recordings for UI changes.
- Keep PRs focused — one logical change per PR.
- Link related issues (e.g.
Closes #123). - All CI checks (lint, test, build) must pass before merge.
- A maintainer will review. Be open to feedback and iterate.
Neru puts a strong emphasis on architectural separation, and platform changes are where that matters most. Before writing Linux or Windows code:
- Read The "One Rule" — non-darwin code must
never import the darwin platform package. It is enforced by both
depguardand an architecture test. - Check the current platform status and capability matrix.
- Work through the Cross-Platform Contributor Guide — it covers file slots, the Linux backend model, CGO guidance, and the bar a platform PR has to clear.
Implement in the existing platform slot rather than inventing new file layout, and keep macOS-specific assumptions out of shared code.
AI-assisted PRs are welcome — the same review bar applies either way. The repo ships shared context so your agent starts from the project's actual rules instead of guessing:
- AGENTS.md is the cross-agent contract (architecture,
commands, conventions).
CLAUDE.mdis a symlink to it, and.cursor/rules/+.github/copilot-instructions.mdpoint at it, so Claude Code, Codex, Cursor, and Copilot all read the same guide. Personal overrides go in gitignoredAGENTS.local.md/CLAUDE.local.md. .agents/skills/holds step-by-step workflows for the changes that are easiest to half-finish — adding a config option, adding a CLI command, platform work — plus contribution mechanics:create-prencodes the commit and PR-template conventions below, andfile-issueencodes the issue forms..claude/skillsis a symlink to it, so Claude Code, Codex, and OpenCode all discover the same skills..claude/agents/holds focused review profiles (platform-boundary-reviewer,deadlock-reviewer) you can run on your diff before opening a PR..claude/settings.jsonwires a format-on-edit hook so agent edits land already formatted. Claude Code asks for one-time workspace trust before running project hooks — that prompt is expected.
Two mechanical notes: CLAUDE.md and .claude/skills are git symlinks (the
same layout Apache Airflow and T3 Code use), so on Windows clone with symlink
support enabled (git config core.symlinks true, requires Developer Mode) or
just read AGENTS.md directly. The layout is pinned by
internal/architecture/agent_contract_test.go.
Whatever tool you use, you own the result: run the pre-commit gate
(just fmt && just lint && just test && just build), read the diff yourself,
and don't submit changes you can't explain.
Not sure where to start? Issues labeled
good first issue
are curated to be well-scoped for newcomers. Beyond those:
- 🐛 Bug fixes — check the open issues
- 📝 Documentation improvements or typo fixes
- 📦 Config examples for common setups
- 🎥 Demo videos or GIFs
- ⚡ Performance improvements
- 🧪 Additional test coverage
For platform work specifically, Contributing safely lists well-scoped starter tasks — and the changes worth opening an issue about first. Longer-term direction is in ROADMAP.md.
Open a GitHub Issue with:
- Your platform (macOS/Linux/Windows and version; on Linux, your desktop
and session type) and Neru version (
neru version). - Steps to reproduce — minimal and specific.
- Expected vs actual behavior.
- Logs — set
log_level = "debug"and attach the relevant lines. Log paths are listed in TROUBLESHOOTING.md. - Screenshots or recordings if the issue is visual.
neru doctor output is useful too — it reports which capabilities your platform
actually supports.
See also: Troubleshooting Guide.
Open a GitHub Issue or start a Discussion describing:
- What you'd like to see.
- Why it would be useful (your use case).
- How you envision it working (optional but helpful).
Thank you for helping make Neru better! 🙏