All docs must canonical, no past commentary, only live state.
CodexMonitor is a Tauri app that orchestrates Codex agents across local workspaces.
- Frontend: React + Vite
- Backend (app): Tauri Rust process
- Backend (daemon):
src-tauri/src/bin/codex_monitor_daemon.rs - Shared backend domain logic:
src-tauri/src/shared/*
The backend separates shared domain logic from environment wiring.
- Shared domain/core logic:
src-tauri/src/shared/* - App wiring and platform concerns: feature folders + adapters
- Daemon wiring and transport concerns:
src-tauri/src/bin/codex_monitor_daemon.rs
src-tauri/src/codex/mod.rssrc-tauri/src/codex/args.rssrc-tauri/src/codex/home.rssrc-tauri/src/codex/config.rs
src-tauri/src/files/mod.rssrc-tauri/src/files/io.rssrc-tauri/src/files/ops.rssrc-tauri/src/files/policy.rs
src-tauri/src/dictation/mod.rssrc-tauri/src/dictation/real.rssrc-tauri/src/dictation/stub.rs
src-tauri/src/workspaces/*
src-tauri/src/shared/*
Root-level single-file features remain at src-tauri/src/*.rs (for example: menu.rs, prompts.rs, terminal.rs, remote_backend.rs).
Shared logic that must work in both the app and the daemon lives under src-tauri/src/shared/.
src-tauri/src/shared/codex_core.rs- Threads, approvals, login/cancel, account, skills, config model
src-tauri/src/shared/workspaces_core.rs- Workspace/worktree operations, persistence, sorting, git command helpers
src-tauri/src/shared/settings_core.rs- App settings load/update, Codex config path
src-tauri/src/shared/files_core.rs- File read/write logic
src-tauri/src/shared/git_core.rs- Git command helpers and remote/branch logic
src-tauri/src/shared/worktree_core.rs- Worktree naming/path helpers and clone destination helpers
src-tauri/src/shared/account.rs- Account helper utilities and tests
Use this mental model when changing backend code:
- Put shared logic in a shared core module.
- Keep app and daemon code as thin adapters.
- Pass environment-specific behavior via closures or small adapter helpers.
The app and daemon do not re-implement domain logic.
The daemon defines wrapper modules named codex and files inside src-tauri/src/bin/codex_monitor_daemon.rs.
These wrappers re-export the daemon’s local modules:
- Codex:
codex_args,codex_home,codex_config - Files:
file_io,file_ops,file_policy
Shared cores use crate::codex::* and crate::files::* paths. The daemon wrappers satisfy those paths without importing app-only modules.
- Composition root:
src/App.tsx - Feature slices:
src/features/ - Tauri IPC wrapper:
src/services/tauri.ts - Tauri event hub:
src/services/events.ts - Shared UI types:
src/types.ts - Thread item normalization:
src/utils/threadItems.ts - Styles:
src/styles/
- Tauri command registry:
src-tauri/src/lib.rs - Codex adapters:
src-tauri/src/codex/* - Files adapters:
src-tauri/src/files/* - Dictation adapters:
src-tauri/src/dictation/* - Workspaces adapters:
src-tauri/src/workspaces/* - Shared core layer:
src-tauri/src/shared/* - Git feature:
src-tauri/src/git/mod.rs
- Daemon entrypoint:
src-tauri/src/bin/codex_monitor_daemon.rs - Daemon imports shared cores via
#[path = "../shared/mod.rs"] mod shared;
- Composition root: keep orchestration in
src/App.tsx. - Components: presentational only. Props in, UI out. No Tauri IPC.
- Hooks: own state, side effects, and event wiring.
- Utils: pure helpers only in
src/utils/. - Services: all Tauri IPC goes through
src/services/. - Types: shared UI types live in
src/types.ts. - Styles: one CSS file per UI area under
src/styles/.
Keep src/App.tsx lean:
- Keep it to wiring: hook composition, layout, and assembly.
- Move stateful logic/effects into hooks under
src/features/app/hooks/. - Keep Tauri IPC, menu listeners, and subscriptions out of
src/App.tsx.
- Shared logic goes in
src-tauri/src/shared/first. - App and daemon are thin adapters around shared cores.
- Avoid duplicating git/worktree/codex/settings/files logic in adapters.
- Prefer explicit, readable adapter helpers over clever abstractions.
- Do not folderize single-file features unless you are splitting them.
The daemon runs backend logic outside the Tauri app.
Update the daemon when one of these is true:
- A Tauri command is used in remote mode.
- The daemon exposes the same behavior over its JSON-RPC transport.
- Shared core behavior changes and the daemon wiring must pass new inputs.
- Shared behavior or domain logic:
- Add or update code in
src-tauri/src/shared/*.rs.
- Add or update code in
- App-only behavior:
- Update the app adapters or Tauri commands.
- Daemon-only transport/wiring behavior:
- Update
src-tauri/src/bin/codex_monitor_daemon.rs.
- Update
- Implement the core logic in a shared module.
- Wire it in the app.
- Add a Tauri command in
src-tauri/src/lib.rs. - Call the shared core from the appropriate adapter.
- Mirror it in
src/services/tauri.ts.
- Add a Tauri command in
- Wire it in the daemon.
- Add a daemon method that calls the same shared core.
- Add the JSON-RPC handler branch in
codex_monitor_daemon.rs.
- Shared git unit wrapper:
workspaces_core::run_git_command_unit(...)
- App spawn adapter:
spawn_with_app(...)insrc-tauri/src/workspaces/commands.rs
- Daemon spawn adapter:
spawn_with_client(...)insrc-tauri/src/bin/codex_monitor_daemon.rs
- Daemon wrapper modules:
mod codex { ... }andmod files { ... }incodex_monitor_daemon.rs
If you find yourself copying logic between app and daemon, extract it into src-tauri/src/shared/.
- Backend spawns
codex app-serverusing thecodexbinary. - Initialize with
initializeand theninitialized. - Do not send requests before initialization.
- JSON-RPC notifications stream over stdout.
- Threads are listed via
thread/listand resumed viathread/resume. - Archiving uses
thread/archive.
The app uses a shared event hub so each native event has one listen and many subscribers.
- Backend emits:
src-tauri/src/lib.rsemits events to the main window. - Frontend hub:
src/services/events.tsdefinescreateEventHuband module-level hubs. - React subscription: use
useTauriEvent(subscribeX, handler).
- Emit the event in
src-tauri/src/lib.rs. - Add a hub and
subscribeXhelper insrc/services/events.ts. - Subscribe via
useTauriEventin a hook or component. - Update
src/services/events.test.tsif you add new subscription helpers.
- Workspaces live in
workspaces.jsonunder the app data directory. - Settings live in
settings.jsonunder the app data directory. - On launch, the app connects each workspace once and loads its thread list.
- UI layout or styling:
src/features/*/components/*andsrc/styles/*
- App-server events:
src/features/app/hooks/useAppServerEvents.ts
- Tauri IPC shape:
src/services/tauri.tsandsrc-tauri/src/lib.rs
- Shared backend behavior:
src-tauri/src/shared/*
- Workspaces/worktrees:
- Shared core:
src-tauri/src/shared/workspaces_core.rs - App adapters:
src-tauri/src/workspaces/* - Daemon wiring:
src-tauri/src/bin/codex_monitor_daemon.rs
- Shared core:
- Settings and Codex config:
- Shared core:
src-tauri/src/shared/settings_core.rs - App adapters:
src-tauri/src/codex/config.rs,src-tauri/src/settings/mod.rs - Daemon wiring:
src-tauri/src/bin/codex_monitor_daemon.rs
- Shared core:
- Files:
- Shared core:
src-tauri/src/shared/files_core.rs - App adapters:
src-tauri/src/files/*
- Shared core:
- Codex threads/approvals/login:
- Shared core:
src-tauri/src/shared/codex_core.rs - App adapters:
src-tauri/src/codex/* - Daemon wiring:
src-tauri/src/bin/codex_monitor_daemon.rs
- Shared core:
useThreads is a composition layer that wires focused hooks and shared utilities.
- Orchestration:
src/features/threads/hooks/useThreads.ts - Actions:
src/features/threads/hooks/useThreadActions.ts - Approvals:
src/features/threads/hooks/useThreadApprovals.ts - Event handlers:
src/features/threads/hooks/useThreadEventHandlers.ts - Messaging:
src/features/threads/hooks/useThreadMessaging.ts - Storage:
src/features/threads/hooks/useThreadStorage.ts - Status helpers:
src/features/threads/hooks/useThreadStatus.ts - Selectors:
src/features/threads/hooks/useThreadSelectors.ts - Rate limits:
src/features/threads/hooks/useThreadRateLimits.ts - Collab links:
src/features/threads/hooks/useThreadLinking.ts
npm install
npm run tauri devnpm run tauri buildnpm run typechecknpm run testnpm run test:watchAt the end of a task:
- Run
npm run lint. - Run
npm run testwhen you touched threads, settings, updater, shared utils, or backend cores. - Run
npm run typecheck. - If you changed Rust backend code, run
cargo checkinsrc-tauri.
- The window uses
titleBarStyle: "Overlay"and macOS private APIs for transparency. - Avoid breaking JSON-RPC format; the app-server is strict.
- App settings and Codex feature toggles are best-effort synced to
CODEX_HOME/config.toml. - UI preferences live in
localStorage. - GitHub issues require
ghto be installed and authenticated. - Custom prompts are loaded from
$CODEX_HOME/prompts(or~/.codex/prompts).
- Use
pushErrorToastfromsrc/services/toasts.tsfor user-facing errors. - Toast wiring:
- Hook:
src/features/notifications/hooks/useErrorToasts.ts - UI:
src/features/notifications/components/ErrorToasts.tsx - Styles:
src/styles/error-toasts.css
- Hook: