Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
07f29d0
feat(opencode): migrate CodeNomad to native V2
pascalandr Aug 12, 2026
c66aac7
fix(opencode): harden the shared V2 runtime
pascalandr Aug 13, 2026
e94d788
fix(restore): migrate legacy OpenCode startup state
pascalandr Aug 14, 2026
a4ccc3a
fix(v2): restore session routing and isolate client state
pascalandr Aug 14, 2026
4b96f46
fix(v2): complete native runtime parity
pascalandr Aug 14, 2026
c025bfc
merge(dev): integrate desktop workspace controls
pascalandr Aug 14, 2026
9a53e2f
fix(v2): isolate runtime defaults
pascalandr Aug 14, 2026
e996196
fix(v2): follow current OpenCode runtime
pascalandr Aug 14, 2026
04cb287
fix(v2): isolate Windows WebView state
pascalandr Aug 15, 2026
d7efb4b
fix(v2): stabilize streaming and startup restore
pascalandr Aug 15, 2026
39d5138
fix(v2): render native response deltas progressively
pascalandr Aug 15, 2026
e4595fb
fix(v2): sustain native response streaming
pascalandr Aug 15, 2026
20de5d2
fix(v2): preserve virtual timeline navigation
pascalandr Aug 16, 2026
37af6c8
Merge branch 'dev' into DEV-v2
pascalandr Aug 17, 2026
485731c
fix(v2): stabilize native restoration and form handling
pascalandr Aug 18, 2026
aca2e4c
fix(ci): make WSL and spawn tests portable
pascalandr Aug 18, 2026
34c1831
fix(settings): preserve migrated database variables
pascalandr Aug 18, 2026
929cc6e
fix(ui): replace duplicate legacy questions with V2 forms
pascalandr Aug 18, 2026
18919e1
feat(ui): show short V2 form choices inline
pascalandr Aug 18, 2026
fd1fd55
fix(native): reconcile cross-host startup markers
pascalandr Aug 18, 2026
61cb41e
fix(ui): apply late native scroll seeds
pascalandr Aug 18, 2026
b0e1714
ci(windows): serialize native lifecycle tests
pascalandr Aug 18, 2026
3c98f45
fix(server): keep timer types portable
pascalandr Aug 18, 2026
59a48f7
fix(ui): keep long native choices compact
pascalandr Aug 18, 2026
db3bfbc
fix(ui): map V2 workspace request selectors
pascalandr Aug 18, 2026
3bfaaaf
perf(ui): target V2 state invalidations
pascalandr Aug 18, 2026
cfb970d
refactor(events): preserve native V2 envelopes
pascalandr Aug 18, 2026
b2a97a8
perf(ui): resync only after reconnects
pascalandr Aug 18, 2026
7e99df9
fix(ui): wait for paginated restore anchors
pascalandr Aug 18, 2026
0cac5ca
fix(ui): release follow on middle-button scroll
pascalandr Aug 18, 2026
d2783ee
fix(ui): render prompts before native admission
pascalandr Aug 18, 2026
ae6a2a8
fix(ui): preserve streaming follow invariants
pascalandr Aug 18, 2026
c4bc08e
fix(settings): restore OpenCode V2 updates
pascalandr Aug 18, 2026
1419821
docs(v2): make runtime handoff procedure explicit
pascalandr Aug 18, 2026
97d4645
fix(ui): stabilize V2 runtime status panels
pascalandr Aug 18, 2026
e4a2bde
fix(server): expose active V2 plugin metadata
pascalandr Aug 18, 2026
68abdc6
fix(i18n): describe active plugin state
pascalandr Aug 18, 2026
a820f80
fix(ui): keep native forms visually stable
pascalandr Aug 18, 2026
775c6c6
refactor(v2): remove dead migration scaffolding
pascalandr Aug 18, 2026
4c65e60
test(v2): remove redundant migration coverage
pascalandr Aug 18, 2026
fe12ff0
ci(v2): authorize stacked migration PRs
pascalandr Aug 18, 2026
4359b4b
fix(v2): align with current OpenCode client contract
pascalandr Aug 18, 2026
249a96e
fix(v2): close native integration review gaps
pascalandr Aug 19, 2026
ef70a8b
fix(v2): harden reconciliation and worktree rollback
pascalandr Aug 19, 2026
af22f58
fix(ui): replace optimistic prompt after native projection
pascalandr Aug 19, 2026
3b5f443
style(ui): remove trailing whitespace
pascalandr Aug 19, 2026
affdb96
fix(v2): keep forms and worktree deletion fail-safe
pascalandr Aug 19, 2026
a2d5df9
fix(forms): allow required custom select values
pascalandr Aug 19, 2026
e1987b9
fix(v2): decouple runtime CLI version
pascalandr Aug 19, 2026
109a8ee
fix(ui): reconcile prompt admission identity
pascalandr Aug 19, 2026
5484f9c
fix(v2): use native shells for background processes
pascalandr Aug 19, 2026
b5f3fc6
feat(v2): unify global service and desktop windows
pascalandr Aug 20, 2026
ec543e3
test(server): support configured TypeScript target
pascalandr Aug 20, 2026
2c9ced6
fix(v2): harden reconnect and desktop state recovery
pascalandr Aug 20, 2026
db0464f
fix(v2): stabilize catalog and transcript loading
pascalandr Aug 20, 2026
52a9589
fix(ui): keep session hydration state accurate
pascalandr Aug 20, 2026
161aebb
fix(workspaces): restore duplicate folder tabs
pascalandr Aug 20, 2026
8fe238f
refactor(workspaces): inline canonical path resolution
pascalandr Aug 20, 2026
a3f7e3b
refactor(electron): remove obsolete single-window lifecycle
pascalandr Aug 20, 2026
f03a17a
docs(v2): document the complete migration scope
pascalandr Aug 20, 2026
3417916
fix(v2): close current desktop parity gaps
pascalandr Aug 20, 2026
6ef68ed
refactor(v2): remove verified dead migration code
pascalandr Aug 20, 2026
ab9b857
docs(v2): record official desktop comparison
pascalandr Aug 20, 2026
290ad3d
fix(v2): harden state authority across reconnects
pascalandr Aug 21, 2026
2a29836
test(server): avoid ES2022 array access
pascalandr Aug 21, 2026
2f08770
fix(ui): restore V2 sessions without blocking first paint
pascalandr Aug 21, 2026
8f5aad8
fix(electron): make failed client-state release retryable
pascalandr Aug 21, 2026
2714fab
fix(electron): block close when renderer state cannot persist
pascalandr Aug 21, 2026
c51e40e
fix(server): harden shared location ownership cleanup
pascalandr Aug 21, 2026
08dd380
fix(v2): preserve shared service and worktree authority
pascalandr Aug 21, 2026
7df0974
fix(desktop): serialize V2 navigation and process shutdown
pascalandr Aug 21, 2026
3445de6
fix(ui): restore shell status and reasoning details
pascalandr Aug 21, 2026
be6cf9f
fix(electron): retain state ownership after failed drain
pascalandr Aug 21, 2026
082ba90
fix(server): fence worktree deletion against session admission
pascalandr Aug 21, 2026
4c702cd
fix(ui): bound retained shell output
pascalandr Aug 21, 2026
7a8d06d
fix(tauri): serialize CLI restart with shutdown
pascalandr Aug 21, 2026
b78697f
fix(server): drain session mutations before worktree deletion
pascalandr Aug 21, 2026
006522f
fix(server): fence deletion through upstream completion
pascalandr Aug 21, 2026
97ebfe5
fix(electron): recover CLI after failed state release
pascalandr Aug 21, 2026
d9b0755
fix(tauri): bound CLI restart shutdown authority
pascalandr Aug 21, 2026
12563d2
fix(ui): preserve shell output truncation boundaries
pascalandr Aug 21, 2026
8ac7453
fix(server): fence worktrees by physical identity
pascalandr Aug 21, 2026
00fcee3
fix(ui): truncate shell output at safe boundaries
pascalandr Aug 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion .github/workflows/comment-pr-artifacts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
shell: bash
run: |
set -euo pipefail
if [ "$BASE_REF" = "dev" ]; then
if [ "$BASE_REF" = "dev" ] || [ "$BASE_REF" = "DEV-v2" ]; then
echo "allowed=true" >> "$GITHUB_OUTPUT"
exit 0
fi
Expand Down
33 changes: 28 additions & 5 deletions .github/workflows/pr-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
shell: bash
run: |
set -euo pipefail
if [ "$BASE_REF" = "dev" ]; then
if [ "$BASE_REF" = "dev" ] || [ "$BASE_REF" = "DEV-v2" ]; then
echo "allowed=true" >> "$GITHUB_OUTPUT"
exit 0
fi
Expand Down Expand Up @@ -104,41 +104,64 @@ jobs:
- name: Test changed runnable UI behavior
run: >-
node --import tsx --test
packages/ui/src/components/browser-frame-security.test.ts
packages/ui/src/components/message-timeline-v2.test.ts
packages/ui/src/components/provider-auth/provider-options.test.ts
packages/ui/src/components/session/session-bottom-pin-intent.test.ts
packages/ui/src/components/session/session-idle-attention.test.ts
packages/ui/src/components/session-list-visibility.test.ts
packages/ui/src/components/unified-picker-path.test.ts
packages/ui/src/components/virtual-follow-behavior.test.ts
packages/ui/src/lib/client-identity.test.ts
packages/ui/src/lib/filesystem-events.test.ts
packages/ui/src/lib/hooks/use-app-session-capture.test.ts
packages/ui/src/lib/hooks/use-instance-metadata.test.ts
packages/ui/src/lib/hooks/use-foreground-refresh.test.ts
packages/ui/src/lib/hooks/use-electron-folder-launch.test.ts
packages/ui/src/lib/launch-errors.test.ts
packages/ui/src/lib/message-selection-position.test.ts
packages/ui/src/lib/model-visibility.test.ts
packages/ui/src/lib/runtime-env.test.ts
packages/ui/src/lib/trailing-resync.test.ts
packages/ui/src/stores/abort-created-workspace-cleanup.test.ts
packages/ui/src/stores/app-session-reconciliation.test.ts
packages/ui/src/stores/app-session-restore-gate.test.ts
packages/ui/src/stores/app-session-restore-queue.test.ts
packages/ui/src/stores/app-session-restore-timeout.test.ts
packages/ui/src/stores/app-session-snapshot-merge.test.ts
packages/ui/src/stores/restore-workspace-commit-gates.test.ts
packages/ui/src/stores/client-state-codec.test.ts
packages/ui/src/stores/client-state-partitions.test.ts
packages/ui/src/stores/client-state.test.ts
packages/ui/src/stores/instances-restore-cancellation.test.ts
packages/ui/src/stores/message-prompt-display.test.ts
packages/ui/src/stores/message-v2/instance-store.test.ts
packages/ui/src/stores/message-v2/message-hydration-authority.test.ts
packages/ui/src/stores/message-v2/message-status.test.ts
packages/ui/src/stores/message-v2/normalizers.test.ts
packages/ui/src/stores/shell-store.test.ts
packages/ui/src/stores/session-generation-recovery.test.ts
packages/ui/src/stores/session-metadata.test.ts
packages/ui/src/stores/session-pagination.test.ts
packages/ui/src/stores/session-pending-state.test.ts
packages/ui/src/stores/workspace-load-readiness.test.ts
packages/ui/src/types/session.test.ts
packages/ui/src/stores/workspace-list-reconciliation-fence.test.ts

- name: Test restore ownership integration
run: >-
node --conditions=browser --import tsx --test --test-force-exit
packages/ui/src/components/form-request-tool-target.test.ts
packages/ui/src/components/form-request.test.ts
packages/ui/src/lib/hooks/use-active-session-message-load.test.ts
packages/ui/src/stores/app-tabs.test.ts
packages/ui/src/stores/forms.test.ts
packages/ui/src/stores/instances-restore-ownership.test.ts
packages/ui/src/stores/opencode-data.test.ts
packages/ui/src/stores/permission-lifecycle.test.ts
packages/ui/src/stores/shell-store-reactivity.test.ts
packages/ui/src/stores/session-actions.test.ts
packages/ui/src/stores/session-native-events.test.ts
packages/ui/src/stores/session-request-authority.test.ts
packages/ui/src/stores/session-send-lifecycle.test.ts
packages/ui/src/stores/session-status.test.ts

- name: Test server
run: node --import tsx --test "packages/server/src/**/*.test.ts"
Expand Down Expand Up @@ -184,4 +207,4 @@ jobs:

- name: Test Tauri crate on Windows
working-directory: packages/tauri-app/src-tauri
run: cargo test --locked
run: cargo test --locked -- --test-threads=1
4 changes: 2 additions & 2 deletions .github/workflows/restrict-non-dev-prs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ permissions:

jobs:
restrict-non-dev-prs:
if: ${{ github.event.pull_request.base.ref != 'dev' }}
if: ${{ github.event.pull_request.base.ref != 'dev' && github.event.pull_request.base.ref != 'DEV-v2' }}
runs-on: ubuntu-latest
env:
ALLOWED_ACTORS: ${{ vars.ALLOWED_NON_DEV_PR_ACTORS }}
Expand All @@ -39,7 +39,7 @@ jobs:
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh pr comment "$PR_NUMBER" --body "Thanks for the contribution. PRs need to target \`dev\` branch. Please retarget this PR to the dev branch"
gh pr comment "$PR_NUMBER" --body "Thanks for the contribution. PRs need to target the \`dev\` or \`DEV-v2\` branch. Please retarget this PR to an authorized development branch."

- name: Close unauthorized PR
if: ${{ steps.auth.outputs.authorized != 'true' }}
Expand Down
224 changes: 76 additions & 148 deletions .opencode/skills/codenomad-architecture-guide/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,153 +1,81 @@
---
name: codenomad-architecture-guide
description: |
Comprehensive architecture and SDK navigation guide for the CodeNomad codebase.

**When to use:** Load this skill when you need to navigate the CodeNomad monorepo, understand cross-package dependencies, work with the OpenCode SDK V2, or ensure you don't miss related code when implementing features or fixing bugs. This skill covers the 6 functional areas (ServerBackend, UserInterface, DesktopClient, SpeechAndAudio, BuildAndPackaging, CloudflareDeployment), OpenCode SDK V2 integration patterns, critical schema behaviors, and feature traces with decision branches.

**Trigger contexts:** Working on CodeNomad features, debugging cross-area issues, integrating OpenCode SDK APIs, adding UI components, implementing server routes, or navigating the monorepo structure.

**Permission required:** Agent must explicitly request or be granted permission to load this skill.
Architecture and native OpenCode V2 navigation guide for CodeNomad. Use for cross-package changes, OpenCode client calls, server routes, events, workspaces, Git, Yolo, UI, or desktop integration. Permission is required before loading.
---

# CodeNomad Architecture & SDK Navigation Skill

## Quick Start (by contribution frequency)

- **UI component/feature (60%)** → Read `references/ui-conventions.md` → Check i18n
- **Server route/feature (25%)** → Read `references/server-conventions.md` → Check `references/feature-traces.md`
- **Bug fix (10%)** → Use Navigation Guide below → Check `references/feature-traces.md`
- **Desktop/Plugin (5%)** → Read `references/desktop-conventions.md`
- **Not covered?** → See "Escape Hatch" at bottom

## 1. Architecture Overview

CodeNomad is a multi-platform desktop application with a Fastify backend and SolidJS frontend.

### 6 Functional Areas (from RPG analysis)

| Area | Entities | Key Responsibility |
|------|----------|-------------------|
| **UserInterface** | 613 | SolidJS components, stores, hooks, i18n, API client |
| **ServerBackend** | 418 | Fastify routes, auth, workspaces, filesystem, speech |
| **SpeechAndAudio** | 74 | Speech synthesis, voice mode, conversation mode |
| **DesktopClient** | 59 | Electron main, Tauri Rust, preload, IPC |
| **BuildAndPackaging** | 28 | Build scripts, packaging, resource bundling |
| **CloudflareDeployment** | 3 | Edge deployment, asset serving |

### Package Map

- `packages/server/` — Fastify backend, workspaces, auth, speech, sidecars
- `packages/ui/` — SolidJS frontend, stores, components, i18n
- `packages/electron-app/` — Electron desktop wrapper
- `packages/tauri-app/` — Tauri desktop wrapper (Rust + webview)
- `packages/opencode-plugin/` — OpenCode plugin integration

### Key Entry Points

- **Server:** `packages/server/src/index.ts` (CLI entry)
- **UI:** `packages/ui/src/main.tsx` (app bootstrap)
- **Electron:** `packages/electron-app/electron/main/main.ts`
- **Tauri:** `packages/tauri-app/src-tauri/src/main.rs`

## 2. Navigation Guide

### Finding Code in the Codebase

Use grep and file search tools to navigate:

**Search by intent:**
- `grep "permission approval" packages/ui/src/components/`
- `grep "session list" packages/ui/src/stores/`
- `grep "workspace create" packages/server/src/server/routes/`

**Search by imports:**
- Find what uses a module: `grep "import.*from.*module-path" packages/`
- Find exports: `grep "^export" packages/server/src/api-types.ts`

**Cross-reference by feature:**
- Server API types: `packages/server/src/api-types.ts`
- UI type mirrors: `packages/ui/src/types/`
- SDK wrappers: `packages/ui/src/lib/sdk-manager.ts`

## 3. SDK Schema Verification (Mandatory)

**SDK Note:** The OpenCode SDK is an external package (`@opencode-ai/sdk/v2/client`). Its implementation lives outside this repository.

- After `npm install`, you can inspect types in `node_modules/@opencode-ai/sdk/v2/client.d.ts`
- **Fallback:** Read the actual usage patterns in CodeNomad code (see `references/sdk-api-reference.md` for file locations)
- When in doubt, check how the SDK is imported and used in existing CodeNomad files

This skill provides navigation and patterns, not definitive schemas.

## 4. Anti-Patterns

### Common Mistakes

| Mistake | Correct Approach | Reference |
|---------|-----------------|-----------|
| Import `enMessages` directly | Use `t()` or `tGlobal()` | `packages/ui/src/lib/i18n/index.tsx` |
| Set `metadata: { flag: true }` on assistant parts | Use client-side registry | `packages/ui/src/stores/session-compaction.ts` |
| Call `client.session.*` directly without worktree routing | Use `getOrCreateWorktreeClient()` | `packages/ui/src/stores/worktrees.ts` |
| Forget SSE disconnection handling | Add handlers | `packages/ui/src/lib/event-source-handlers.ts` |
| Add hardcoded strings without i18n | Add to English + all 7 locales | `packages/ui/src/lib/i18n/messages/` |
| Modify server route without checking UI API client | Trace full feature flow | `references/feature-traces.md` |
| Change API type without checking UI type matches | Check UI types mirror server types | `packages/ui/src/types/` vs `packages/server/src/api-types.ts` |

## 5. Platform Integration Checklist

### Desktop Platform Rules

- **Existing IPC/handlers (pre-Tauri):** MUST implement in both Electron + Tauri
- **New features:** Implement in Electron first, Tauri if time permits
- **Native APIs (dialogs, notifications):** Use `packages/ui/src/lib/native/` abstraction

### Checklist

- [ ] Electron main-process changes? (`packages/electron-app/electron/main/`)
- [ ] Tauri Rust changes? (`packages/tauri-app/src-tauri/src/`)
- [ ] Preload API exposure? (`packages/electron-app/electron/preload/`)
- [ ] Native abstraction? (`packages/ui/src/lib/native/`)

## 6. Implementation Checklist

Before submitting changes:

- [ ] Run impact analysis: `grep "YOUR_EXPORT_NAME" packages/` to find all usages
- [ ] Check i18n: Search for hardcoded strings in modified files
- [ ] Verify file length: Check line count (warn >500, reject >800 source; >1000 tests)
- [ ] Check DesktopClient: Does this need IPC/main-process changes?
- [ ] Verify SDK compatibility: Check types in `node_modules/@opencode-ai/sdk/v2/client.d.ts`
- [ ] Cross-area check: If modifying server routes, check UI stores and API clients
- [ ] Check anti-patterns: Review "Common Mistakes" section above
- [ ] API compatibility: If changing `api-types.ts`, check UI type matches

## 7. Escape Hatch + Update Criteria

### Not Covered?

If your change involves areas not documented here:

1. Read package entry points and scan directory structure
2. Ask the user before proceeding with unfamiliar code

### Update This Skill If

- You discover a new SDK gotcha not documented in `references/sdk-critical-behaviors.md`
- You add a new cross-area feature flow (add to `references/feature-traces.md`)
- File paths or conventions change significantly
- You find an anti-pattern occurring repeatedly
- SDK schemas change and examples become outdated

## Reference Files

| File | Purpose |
|------|---------|
| `references/architecture-overview.md` | Package structure, functional areas, entry points |
| `references/ui-conventions.md` | SolidJS, i18n, stores, components, testing |
| `references/server-conventions.md` | Fastify, API types, config, testing |
| `references/desktop-conventions.md` | Electron + Tauri parity, native abstractions |
| `references/sdk-api-reference.md` | OpenCode SDK V2 categories and signatures |
| `references/sdk-critical-behaviors.md` | Schema gotchas, limitations, decision matrix |
| `references/sdk-integration-patterns.md` | Client lifecycle, error handling, optimistic updates |
| `references/feature-traces.md` | End-to-end flows with decision branches |
# CodeNomad Architecture Guide

## Start Here

- UI: read `references/ui-conventions.md`; use i18n for visible text.
- Server: read `references/server-conventions.md` and `references/feature-traces.md`.
- OpenCode: read the three `sdk-*.md` references before changing client calls or service lifecycle.
- Desktop: read `references/desktop-conventions.md`.

## Native OpenCode V2 Baseline

- The only OpenCode client dependency is the experimental `@opencode-ai/client` protocol. Server and UI stay on the same reviewed release; the selected runtime CLI is independently updated and validated through service/API compatibility rather than an exact version gate. Current public `@opencode-ai/sdk` docs describe a different contract.
- Do not use `@opencode-ai/sdk`, `@opencode-ai/sdk/v2/client`, or `createOpencodeClient()`; follow installed `@opencode-ai/client` declarations.
- There is no `packages/opencode-plugin/`. Do not restore plugin tools, plugin routes, or plugin packaging.
- The server uses the selected host or WSL CLI's official `service status`, `service start`, and `service get password` lifecycle to connect to one externally owned global OpenCode daemon. It owns no private port/database/registration/PID and never stops the daemon on backend shutdown. WSL requires Windows localhost forwarding and uses no cross-namespace PID operations.
- The UI uses generated Promise clients from `OpenCode.make()` through the CodeNomad proxy.
- OpenCode owns session APIs, native Forms, session Shell (`client.session.shell`), session instructions (`client.session.instructions.entry`), location-scoped background Shells, and interactive PTYs. Question request/reply/reject routes are compatibility-only; new interruption flows use `client.form.*`. The Status panel lists `client.shell.*` records, refreshes on Shell events/reconnect, displays native metadata, and supports ownership-checked removal. Interactive `client.pty.*` terminals remain separate.
- CodeNomad owns explicit Stop Workspace eviction, directory authorization, Git status/diff/stage/unstage/commit, Yolo persistence/auto-replies, and `/api/events`. Tab/window close only detaches local UI and never evicts.
- OpenCode owns the global daemon's standard state and database. Allowed configured environment variables apply only to `service start` for a missing daemon; an existing daemon is unchanged, and `OPENCODE_DB`/`XDG_STATE_HOME` ownership settings are ignored.
- Native desktop identity is channel plus config profile: one singleton process/backend per profile, multiple UUID windows, second-launch focus by default, and `--new-window` for another window. Stable/dev/non-default profiles isolate native state; OpenCode sessions/messages are shared while tabs/drafts/views are per-window.
- Client-state V3 is a per-window envelope over the V2 content-addressed partition graph with atomic publication/migration, ownership-fenced writes, and conservative post-commit GC. Native SideCar/browser previews are sandboxed without same-origin access; DOM comment inspection is web-only.

## Package Map

- `packages/server/`: Fastify control API, shared OpenCode service, locations, auth, filesystem, Git, Yolo, speech.
- `packages/ui/`: SolidJS application, generated client adapters, stores, components, i18n.
- `packages/electron-app/`: Electron host.
- `packages/tauri-app/`: Tauri host.
- `packages/cloudflare/`: edge deployment.

## Integration Paths

- Shared service: `packages/server/src/workspaces/opencode-service.ts`
- Location ownership: `packages/server/src/workspaces/manager.ts`
- OpenCode proxy: `packages/server/src/server/http-server.ts`
- CodeNomad API client/events: `packages/ui/src/lib/api-client.ts`
- OpenCode client cache: `packages/ui/src/lib/sdk-manager.ts`
- Root client authority: `packages/ui/src/stores/opencode-client.ts`
- Native session calls: `packages/ui/src/stores/session-api.ts`, `session-actions.ts`
- Git mutations: `packages/server/src/workspaces/git-mutations.ts`
- Yolo: `packages/server/src/permissions/`, `packages/server/src/server/routes/yolo.ts`
- Desktop hosts: `packages/electron-app/electron/main/`, `packages/electron-app/electron/preload/index.cjs`, `packages/tauri-app/src-tauri/src/`

## Rules

- Inspect installed declarations under `node_modules/@opencode-ai/client/dist/promise/`; generated names are the source of truth.
- Preserve `LocationRef` and explicit directory routing. Never infer workspace ownership from a client-provided path.
- Send CodeNomad operations through `/api/*`; send OpenCode operations through `/workspaces/:id/instance/api/*`.
- Consume the multiplexed CodeNomad SSE stream at `/api/events`; do not create one OpenCode process or event stream per workspace. Native events are volatile, so reconnect must reconcile authoritative state.
- Treat the instance proxy allowlist as an integration boundary. Upstream routes are not exposed automatically.
- Keep Git mutations and Yolo in CodeNomad. They are policy/security boundaries, not upstream client features.
- Check `packages/server/src/api-types.ts` and UI consumers together when changing CodeNomad events or responses.
- Desktop behavior must remain at strict Electron/Tauri parity in the same change; use the shared native abstraction and test both hosts.

## Anti-Patterns

| Avoid | Use |
|---|---|
| Public `@opencode-ai/sdk` examples | Installed experimental `@opencode-ai/client` declarations |
| One `opencode serve` per workspace | One externally owned global daemon through the official CLI lifecycle |
| Per-worktree clients/processes | Root proxy client plus native location/directory inputs |
| Reintroducing `packages/opencode-plugin` or server plugin/background-process paths | Native session Shell/instructions, background `shell.*`, and separate interactive `pty.*` management |
| OpenCode APIs for stage/commit/Yolo policy | CodeNomad routes and managers |
| Hardcoded UI strings | `t()` / `tGlobal()` and every locale |

## References

- `references/architecture-overview.md`
- `references/server-conventions.md`
- `references/sdk-api-reference.md`
- `references/sdk-integration-patterns.md`
- `references/sdk-critical-behaviors.md`
- `references/feature-traces.md`
- `references/ui-conventions.md`
- `references/desktop-conventions.md`
Loading
Loading