# Contributing to CodeNomad Thank you for your interest in contributing! This guide will help you get started. ## Prerequisites - **Node.js 18+** and npm - **OpenCode CLI** in your `PATH` (CodeNomad uses one shared native V2 service for all workspace locations) ## Quick Start ```bash git clone https://github.com/NeuralNomadsAI/CodeNomad.git cd CodeNomad npm install npm run dev ``` ## Finding Issues to Work On Browse [open issues](https://github.com/NeuralNomadsAI/CodeNomad/issues) and look for these labels: | Label | Meaning | |---|---| | `ready-to-work` | Clear scope, ready for anyone to pick up | | `good-first-issue` | Good for first-time contributors | | `enhancement` | New feature requests | | `bug` | Bug reports | **Before starting:** comment on the issue so we can discuss approach and avoid duplicate work. ## Development Workflow ### 1. Fork and Branch ```bash # Fork the repo on GitHub, then clone your fork git clone https://github.com/YOUR_USERNAME/CodeNomad.git cd CodeNomad # Add the upstream remote git remote add upstream https://github.com/NeuralNomadsAI/CodeNomad.git # Create a branch from upstream/dev git fetch upstream git checkout -b fix/your-branch-name upstream/dev ``` ### 2. Branch Naming | Prefix | Use for | |---|---| | `fix/` | Bug fixes | | `feat/` | New features | | `docs/` | Documentation changes | | `refactor/` | Code refactoring | | `chore/` | Build, config, maintenance | Examples: `fix/question-queue-ordering`, `feat/retry-tool-call`, `docs/contributing-guide` ### 3. Make Your Changes ```bash # Install dependencies npm install # Run the dev server npm run dev # Run type checking npm run typecheck --workspace @codenomad/ui ``` ### 4. Commit Write clear, descriptive commit messages. Explain **what** changed and **why**. ```bash git add . git commit -m "fix(ui): preserve question queue order when upserting duplicate requests When a question arrives as a global entry and later resolves to a tool part with a newer timestamp, the original enqueue time was lost, causing the question to move behind newer entries and break interruption order." ``` ### 5. Push and Create a PR ```bash git push origin your-branch-name ``` Then open a pull request on GitHub targeting the `dev` branch. **PR checklist:** - [ ] Branch is based on latest `upstream/dev` - [ ] One issue per PR (don't mix unrelated changes) - [ ] Type checking passes: `npm run typecheck` (root) or the workspace-specific script matching your change area - [ ] Tests pass (if applicable) - [ ] PR description explains the change, includes relevant screenshots for UI changes, and links related issues when applicable ## Project Structure | Package | Description | |---|---| | `packages/server` | Core logic & CLI — workspaces, OpenCode proxy, API, auth | | `packages/ui` | SolidJS frontend — reactive UI components and stores | | `packages/electron-app` | Electron desktop shell | | `packages/tauri-app` | Tauri desktop shell (experimental) | | `packages/cloudflare` | Cloudflare deployment adapters | ### OpenCode V2 Boundaries - Server, UI, and the selected `opencode2` CLI must use the exact `@opencode-ai/client` version pinned by the server package. Startup probes and rejects mismatched CLIs. Review OpenCode release notes, current documentation, and installed declarations on every upgrade; this is not the public `@opencode-ai/sdk` contract. - Upgrade references: [OpenCode releases](https://github.com/anomalyco/opencode/releases), [OpenCode documentation](https://opencode.ai/docs/), and `node_modules/@opencode-ai/client/dist/promise/`. - `packages/server/src/workspaces/opencode-service.ts` owns a custom lease-locked discovery, launch, process-proof, and authenticated-stop lifecycle. Production does not call `Service.ensure` or `Service.stop` directly. Workspaces are native OpenCode locations/directories, not separate server processes. - V2 always uses `~/.local/share/opencode2/opencode.db`. Never reuse the V1 database for V2. - OpenCode session calls use `/workspaces/:id/instance/api/*`; CodeNomad control routes and multiplexed events use `/api/*` and `/api/events`. - The proxy is method/path allowlisted, so new upstream functionality is not exposed automatically. - Native Shell (`client.session.shell`) and prompt instructions (`client.session.instructions.entry`) remain separate from native V2 PTY management. - Native PTYs are location-scoped and listed in the Status panel. The UI refreshes them on PTY events and reconnect, displays native metadata, and supports title updates and ownership-checked removal. Current installed declarations have no PTY output/read/stream API or separate stop endpoint, so removal is the native stop action for a running PTY. `packages/opencode-plugin` and the server plugin/background-process paths remain deleted and must not be restored. - Native events are volatile. Reconnect handlers must refetch authoritative state instead of assuming missed events will replay. - Git mutations and Yolo policy remain CodeNomad-owned server boundaries. ### Key UI Files | Path | Purpose | |---|---| | `packages/ui/src/stores/session-events.ts` | SSE event handlers (idle, status, permissions, questions) | | `packages/ui/src/stores/session-actions.ts` | User actions (send message, abort, revert, fork) | | `packages/ui/src/stores/message-v2/` | Message store (v2 architecture) | | `packages/ui/src/stores/instances.ts` | Instance management and interruption queues | | `packages/ui/src/components/tool-call.tsx` | Tool call rendering | | `packages/ui/src/components/message-block.tsx` | Message display blocks | | `packages/ui/src/components/session/session-view.tsx` | Main session view | | `packages/ui/src/lib/i18n/messages/` | Translation files (en, es, fr, ja, ru, he, zh-Hans) | > For the package map, native OpenCode V2 integration, ownership boundaries, and feature traces, load the `codenomad-architecture-guide` skill: > `.opencode/skills/codenomad-architecture-guide/SKILL.md` ### Styling - Tokens: `packages/ui/src/styles/tokens.css` - Utilities: `packages/ui/src/styles/utilities.css` - Component styles: `packages/ui/src/styles/components/`, `packages/ui/src/styles/messaging/`, `packages/ui/src/styles/panels/` - Keep style files under ~150 lines; split by component ### Internationalization (i18n) - Use `useI18n()` in components, `tGlobal()` in stores - Messages live in `packages/ui/src/lib/i18n/messages//` - When adding a string: add to `en/` first, then add the same key to every other locale - Placeholders use `{name}` syntax (word characters only) ## Code Principles - **KISS**: Keep modules narrowly scoped - **DRY**: Share helpers before copy-pasting - **Single responsibility**: Split files when concerns diverge - **Composable primitives**: Prefer signals, hooks, utilities over deep inheritance ## Need Help? - Check existing [issues](https://github.com/NeuralNomadsAI/CodeNomad/issues) and [PRs](https://github.com/NeuralNomadsAI/CodeNomad/pulls) - Ask in the issue you're working on - Review the [server documentation](packages/server/README.md) for CLI flags and configuration