CodeNomad/CONTRIBUTING.md
Pascal André 4359b4bfe9
fix(v2): align with current OpenCode client contract
Pin the server and UI client to the installed beta runtime and reject mismatched CLI versions before shared-service startup. Delegate proven shared-service shutdown to Service.stop while retaining CodeNomad lease, peer, registration, endpoint, and process-identity checks.

Adopt native Forms and the client/solid data reducer for live messages, tools, permissions, and input forms. Propagate internal stream generations into authoritative reconnect reconciliation and replace directory-wide session scans with native project cursor pagination.

Fail worktree deletion when session evacuation fails and deduplicate canonical workspace folders instead of exposing non-isolated duplicate instances. Update migration notes and CI coverage for the reviewed contract.

Validated with server/UI/Electron typechecks, 244 UI partition tests, 122 Electron native tests, 248 server tests plus 3 platform skips (the sole Windows cleanup race passed in isolation), UI/server/Electron builds, Tauri cargo check --locked, and git diff --check.
2026-08-19 01:50:39 +02:00

166 lines
7 KiB
Markdown

# 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/<locale>/`
- 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