Contributing
How to fork, develop, write a good PR, follow architecture rules, and get your changes merged into L.U.N.A.
Fork and set up
All contributions go through GitHub pull requests against the main branch.
Fork the repository
Click Fork on github.com/Sehastrajit/Luna. This creates your own copy where you can push changes freely.
Clone your fork
git clone https://github.com/<your-username>/Luna.git
cd Luna
git remote add upstream https://github.com/Sehastrajit/Luna.gitInstall dependencies
npm install
cd frontend && npm install && cd ..
pip install -r backend/requirements.txtCreate your environment file
copy .env.example .envSet at minimum user_name, ollama_model, and embedding_model. See the Environment page for details.
Verify everything works
npm run luna -- doctor
npm run luna -- devBranch naming
Use a consistent prefix so PRs are easy to filter:
| Prefix | Use for | Example |
|---|---|---|
feature/ | New capabilities | feature/spotify-queue-control |
fix/ | Bug fixes | fix/voice-runtime-crash-on-resume |
docs/ | Documentation only | docs/memory-api-reference |
refactor/ | Internal restructuring, no behaviour change | refactor/split-tool-registry |
chore/ | Dependency bumps, config changes | chore/upgrade-electron-32 |
# Always branch from an up-to-date main
git fetch upstream
git checkout -b feature/my-feature upstream/mainCode standards
Backend (Python)
- Routers in
backend/routers/must be thin — validate the request, call a service, return the result. No business logic in routers. - All business logic goes in
backend/services/. Service functions should be importable and testable in isolation. - Background jobs belong in
backend/processes/and must register themselves inregistry.py. - Use type hints on all function signatures.
- Never use
print()for logging — use the Pythonloggingmodule. - Avoid non-ASCII characters in log messages — causes
UnicodeEncodeErroron Windows cp1252.
Frontend (TypeScript / React)
- Components live in
frontend/src/components/<Feature>/— group by domain, not by type. - All backend communication goes through typed wrappers in
frontend/src/api/. No rawfetchcalls in components. - Global state mutations go in
frontend/src/store/index.tsvia Zustand actions. - New reusable hooks go in
frontend/src/hooks/. - Use TypeScript strictly — no
anyunless unavoidable, and document why.
Electron
- All native/Node.js APIs must go through the
contextBridgeinpreload.js. Never expose raw Node APIs to the renderer. - Backend lifecycle management (start, restart, health check) lives in
electron/main.jsonly.
Architecture rules
Read docs/ARCHITECTURE.md before making broad architectural changes. Read docs/PROCESSES.md before changing background job behaviour.
| Rule | Why |
|---|---|
| Business logic in services, not routers | Routers are tested at the HTTP boundary. Services are testable in isolation and reusable across routes. |
| One layer per PR where possible | Mixing backend + frontend + Electron changes makes review hard and widens blast radius. |
| New tools require permission registration | Every new tool must have a default permission mode in tool_registry.py — defaulting to confirm is safest. |
| Agent-created files only in data/workspace/ | Prevents Luna from accidentally modifying source files or user documents outside the sandbox. |
| No hardcoded model names in services | Models are user-configurable via .env. Services must read from config.py. |
PR process
Here is the full flow from your branch to merged:
Run the checks locally
npm run luna -- check # backend syntax
cd frontend && npm run build # TypeScript compileBoth must pass cleanly before opening a PR.
Push and open the PR
git push origin feature/my-featureOpen a PR on GitHub against main. Fill in:
- What changed — clear one-paragraph summary.
- Why — motivation, issue link if applicable.
- How to test — steps the reviewer should follow.
- Screenshots — for any UI change.
Address review feedback
Push new commits to your branch — don't force-push during review as it makes it harder to see what changed. Squash on merge is enabled.
Merge
Once approved, the PR will be squash-merged into main. Your branch is deleted automatically.
PR checklist
Run through this before requesting review:
npm run luna -- checkpasses.cd frontend && npm run buildpasses with no TypeScript errors.- No
.env,data/,*.db, orchroma/files staged. - New backend logic is in
services/, not inrouters/. - New tools are registered in
tool_registry.pywith a default permission mode. - No hardcoded model names — config reads from
config.py. - No
print()statements in backend code — uselogging. - No non-ASCII characters in backend log strings.
- PR description includes what changed, why, and how to test.
- Screenshots included for UI changes.
Privacy rules
- Never commit
.env,data/,*.db,chroma/, or log files. - Do not submit conversation logs, memory exports, or personal data of any kind.
- API keys, tokens, and secrets are never acceptable in source code — use
.envandconfig.py. - If your contribution involves external service calls, document which data is sent and ensure users can opt out via configuration.