All docs must be canonical, with no past commentary, only live state.
This file is the agent contract for how to work in this repo. Detailed navigation/runbooks live in:
docs/codebase-map.md(task-oriented file map: "if you need X, edit Y")README.md(setup, build, release, and broader project docs)docs/shaping/rest-api-migration.md(REST backend architecture and parity status)
OpenCodeMonitor is a fork of CodexMonitor — a Tauri desktop app that orchestrates coding agents across local workspaces. The fork replaces the Codex CLI backend with OpenCode and translates between OpenCode's protocol and the original CodexMonitor frontend event shapes.
We pull upstream CodexMonitor changes regularly (weekly/monthly). The fork's translation layer is isolated to three Rust files so frontend merges stay clean.
- Frontend: React + Vite (
src/) - Backend app: Tauri Rust process (
src-tauri/src/lib.rs) - Backend daemon: JSON-RPC process (
src-tauri/src/bin/codex_monitor_daemon.rs) - Shared backend source of truth:
src-tauri/src/shared/* - Protocol event translation:
src-tauri/src/backend/event_translator.rs
The frontend thread reducer receives events in the same shape as original CodexMonitor. All OpenCode-to-CodexMonitor translation happens in Rust, never in the frontend.
The backend uses opencode serve (HTTP REST + SSE). The translation layer is isolated to three Rust files so frontend merges stay clean:
src-tauri/src/backend/event_translator.rs— protocol events to CodexMonitor event shapessrc-tauri/src/shared/codex_core.rs— all protocol methodssrc-tauri/src/backend/app_server.rs— process spawn, event routing
Internal Rust module paths (codex_core.rs, codex/mod.rs, etc.) are not renamed — only user-facing strings. This minimizes merge conflicts with upstream. (The original CodexMonitor used Codex CLI; this fork uses OpenCode REST instead.)
- Put shared/domain backend logic in
src-tauri/src/shared/*first. - Keep app and daemon as thin adapters around shared cores.
- Do not duplicate logic between app and daemon.
- Keep JSON-RPC method names and payload shapes stable unless intentionally changing contracts.
- Keep frontend IPC contracts in sync with backend command surfaces.
- All OpenCode protocol translation happens in Rust — never in the frontend.
For backend behavior changes, follow this order:
- Shared core (
src-tauri/src/shared/*) when behavior is cross-runtime. - App adapter and Tauri command surface (
src-tauri/src/lib.rs+ adapter module). - Frontend IPC wrapper (
src/services/tauri.ts). - Daemon RPC surface (
src-tauri/src/bin/codex_monitor_daemon/rpc.rs+rpc/*).
If you add a backend command, update all relevant layers and tests.
- Keep
src/App.tsxas composition/wiring root. - Move stateful orchestration into:
src/features/app/hooks/*src/features/app/bootstrap/*src/features/app/orchestration/*
- Keep presentational UI in feature components.
- Keep Tauri calls in
src/services/tauri.tsonly. - Keep event subscription fanout in
src/services/events.ts.
Use project aliases for frontend imports:
@/*->src/*@app/*->src/features/app/*@settings/*->src/features/settings/*@threads/*->src/features/threads/*@services/*->src/services/*@utils/*->src/utils/*
- Frontend composition root:
src/App.tsx - Frontend IPC wrapper:
src/services/tauri.ts - Frontend event hub:
src/services/events.ts - App command registry:
src-tauri/src/lib.rs - Daemon entrypoint:
src-tauri/src/bin/codex_monitor_daemon.rs - Daemon RPC router:
src-tauri/src/bin/codex_monitor_daemon/rpc.rs - Shared workspaces core:
src-tauri/src/shared/workspaces_core.rs+src-tauri/src/shared/workspaces_core/* - Shared git UI core:
src-tauri/src/shared/git_ui_core.rs+src-tauri/src/shared/git_ui_core/* - Protocol event translator:
src-tauri/src/backend/event_translator.rs - Protocol methods:
src-tauri/src/shared/codex_core.rs - Process spawn + event routing:
src-tauri/src/backend/app_server.rs - Threads reducer entrypoint:
src/features/threads/hooks/useThreadsReducer.ts - Threads reducer slices:
src/features/threads/hooks/threadReducer/*
For broader path maps, use docs/codebase-map.md.
When changing backend behavior that can run remotely:
- Shared core logic updated (or explicitly app-only/daemon-only).
- App surface updated (
src-tauri/src/lib.rs+ adapter). - Frontend IPC updated (
src/services/tauri.ts) when needed. - Daemon RPC updated (
rpc.rs+rpc/*) when needed. - Contract/test coverage updated.
Use existing design-system primitives and tokens for shared shell chrome. Do not reintroduce duplicated modal/toast/panel/popover shell styling in feature CSS.
(See existing DS files and lint guardrails for implementation details.)
- Prefer safe git operations (
status,diff,log). - Do not reset/revert unrelated user changes.
- If unrelated changes appear, continue focusing on owned files unless they block correctness.
- If conflicts impact correctness, call them out and choose the safest path.
- Fix root cause, not band-aids.
Run validations based on touched areas:
- Always:
npm run typecheck - Frontend behavior/state/hooks/components:
npm run test - Rust backend changes:
cd src-tauri && cargo check - Use targeted tests for touched modules before full-suite runs when iterating.
Core local commands (keep these inline for daily use):
npm install
npm run doctor:strict
npm run tauri:dev
npm run test
npm run typecheck
cd src-tauri && cargo checkRelease build:
npm run tauri:buildFocused test runs:
npm run test -- <path-to-test-file>Use extra care in high-churn/high-complexity files:
src/App.tsxsrc/features/settings/components/SettingsView.tsxsrc/features/threads/hooks/useThreadsReducer.tssrc-tauri/src/shared/git_ui_core.rssrc-tauri/src/shared/workspaces_core.rssrc-tauri/src/shared/codex_core.rssrc-tauri/src/backend/event_translator.rssrc-tauri/src/backend/app_server.rssrc-tauri/src/bin/codex_monitor_daemon/rpc.rs
- Task-oriented code map:
docs/codebase-map.md - Setup/build/release/test commands:
README.md - REST backend architecture:
docs/shaping/rest-api-migration.md - Frontend event contract:
docs/app-server-events.md - For OpenCode API/feature changes, refer to
opencode-server-api.mdxand./tmp/opencodebefore implementing protocol or behavior updates.
Load project memory: read .memory/SUMMARY.md before starting work. If .memory/ doesn't exist, initialize it per the project-memory skill.