Skip to content

Latest commit

 

History

History
72 lines (59 loc) · 14.5 KB

AGENTS.md

File metadata and controls

72 lines (59 loc) · 14.5 KB

AGENT NOTES

Rules here apply everywhere. Before changing code in an area listed under Area conventions, read that area's document; its rules bind like this file. dev-docs/INDEX.md lists every document.

Styling Guidelines

  • Reuse the existing token & utility layers before introducing new CSS variables or custom properties. Extend src/styles/tokens.css / src/styles/utilities.css if a shared pattern is needed.
  • Place new styles beside their peers in focused files (≈150 lines or less) under src/styles/{components|messaging|panels}/ and @import them from the matching aggregate entry file (src/styles/controls.css, messaging.css, panels.css), which holds only imports. Reusable patterns (buttons, selectors, dropdowns) live in src/styles/components/; never redefine the same utility classes elsewhere.
  • Dialog, popover and floating-window headers, toolbars, bodies, footers, titles and actions use the shared .window-* primitives (src/styles/components/window.css). Persistent utility windows and transcript-covering previews put components/window-close-button.tsx at the upper right of their existing top toolbar, never in a dedicated row; transient popups such as transcript filters dismiss on outside interaction and have no close button.
  • Corners are square unless the user explicitly requests otherwise for a specific change. Round exceptions: Yolo, MCP and plugin activation switches and the lone-setting Settings switch (settings/settings-switch.tsx), all sharing styles/components/switches.css geometry; floating message scroll buttons; tags and numeric/context/token labels via --chip-radius (alias --pill-radius; register badge variants in styles/components/badges.css, use .badge-shape for utility-styled labels, never a local radius). Other chrome, including the fixed panel toggles, stays square.
  • Pick backgrounds by surface role (styles/tokens.css), never by a colour that merely looks close: --surface-field (the base colour) is reserved for what users type into (composer, inputs, textareas, search rows); --surface-canvas for reading areas (transcript, editors, diffs, main panel bodies); --surface-overlay for floating windows, dialogs, popovers, tooltips and every menu or list picker; --surface-inset (also --surface-code) for code, shell, log and diagnostics output and status cards; --surface-control for buttons, segmented controls and select triggers; icon controls that rest flush on a canvas (Files panel toolbars, session header buttons) take the canvas they sit on. The three non-field roles follow the title-bar tint (--surface-shade-strong). Utilities .bg-surface-{field,canvas,overlay,inset} mirror them; consumers that need concrete colours (Monaco, MUI, extension frames) resolve roles through lib/css-color.ts.
  • Menus share one item treatment (--menu-item-hover-bg/--menu-item-selected-bg) across Kobalte menus, selectors and native <select>. styles/components/native-select.css styles every native select globally: the closed control matches selector triggers (control surface, chevron) and, where appearance: base-select and content-box clipping are supported (Electron, WebView2), the open list matches the shared menus and long values stay on one line, clipped before a background-drawn chevron; elsewhere the native select remains. Customizable selects size to the shown value, so auto-width selects need a stable feature width (container units, not percentages of shrink-to-fit parents). Do not style individual selects as fields.
  • The .icon-toggle active state (aria-pressed/aria-expanded/data-active) is one shared rule in styles/utilities.css for every palette; never add per-button or per-palette active overrides (exact tint, exception and contrast test in dev-docs/UI_CONVENTIONS.md).
  • SUID buttons never animate on press (MuiButtonBase disableTouchRipple theme default in lib/theme.tsx), like the Message content trigger; the keyboard focus ripple remains their focus-visible cue, squared in styles/components/buttons.css. Do not re-enable press ripples per component, nor disable the focus ripple without another focus cue.
  • Document new conventions where agents will find them: rules that apply everywhere belong in this file; an area's contract belongs in that area's document, under Agent conventions when it fits nowhere else in the body (create the document and add it to the index below when none fits).
  • Documentation (this file, dev-docs/, skills) describes the current state only. Keep no history: removed features and their names, former behavior ("formerly", "no longer", "replaced by"), PR/commit/date provenance, dated validation logs or abandoned designs; Git holds them. Code that reads older data is described as current behavior. Do not add sentences denying something ("X is not Y", "this does not prove…"); when one would counter a statement elsewhere, correct or delete that statement instead. Prohibitions that tell an agent what never to do remain instructions.

Coding Principles

  • Keep modules narrowly scoped with only the public API callers need (KISS); share helpers through dedicated modules instead of copy/paste (DRY); split files when concerns diverge (state, actions, API, events); prefer composable primitives (signals, hooks, utilities) over deep inheritance or implicit global state; isolate platform integrations (SSE, IPC, SDK) in thin adapters surfacing typed events/actions.
  • Memoize action-menu item arrays (createMemo, or stable per-row arrays) instead of rebuilding them with fresh JSX icons on each evaluation behind <For> or into ActionOverflowMenu. An item whose icon renders in two places at once (inline buttons and the overflow menu, as in FileRowActions or tool-call headers) creates the icon in a getter or comes from an unmemoized builder such as message-block's headerMenuItems: one DOM node cannot be inserted twice.
  • Follow dev-docs/CACHE_REFRESH_CONVENTIONS.md for display snapshots, coalesced trailing refreshes, stale-response fencing and authoritative mutation reads. Check existing feature semantics before adding another cache or refresh policy.
  • CodeNomad integrates with an independently installed and updated OpenCode service: compatibility depends only on the API/capability contracts actually consumed; the versions pinned to build or test CodeNomad only make its own build reproducible. Never turn tested versions into a daemon allowlist or block a runtime/feature only because its version is untested; a version-specific restriction needs a demonstrated failing test or an identified breaking change in a consumed contract, cited with why the restriction is necessary. Review upstream changes and affected callers rigorously (private API use needs contract scrutiny) instead of exhaustively retesting unchanged contracts. Missing capabilities must fail safely without destructive or mass-loading fallbacks.
  • Never modify OpenCode for Missions autonomy: use and qualify existing native service/plugin mechanisms, and never infer an upstream-extension requirement from the absence of a named scheduling API.

Area conventions

Paths are under packages/ui/src/ or packages/server/src/ unless stated.

  • Missions (missions/, opencode/missions-plugin.ts, server/routes/mission-*, host-lifetime/; UI components/mission-*, components/settings/missions-settings-section.tsx, stores/mission-*, styles/panels/mission-*): dev-docs/MISSIONS.md; recurring schedules and Wayfinder human gates (its "Wayfinder human decision mark" section) dev-docs/MISSIONS_RECURRING.md.
  • Questions, permissions and pending-request recovery (interruption dock, permission receipts, question-data.ts, server/routes/pending-requests.ts, workspaces/pending-discovery.ts, stores/pending-recovery-*): dev-docs/NATIVE_INTERRUPTION_UX.md.
  • Composer (components/prompt-input*, prompt-input/, PromptContextControls, /btw): dev-docs/COMPOSER.md.
  • Transcript (message rendering, Message content and presets, token lines, tool renderers, stores/message-v2/, stores/opencode-data.ts, lib/native-execution-events.ts): dev-docs/TRANSCRIPT.md; long-text bounds dev-docs/TEXT_DISPLAY_BOUNDS.md.
  • Timeline, transcript scrolling and history search (virtual-follow-list.tsx, timeline-*, stores/timeline-previews.ts, history search): dev-docs/SESSION_HISTORY_NAVIGATION.md, dev-docs/SESSION_HISTORY_QUERIES.md.
  • Shell, panels, tabs, session sidebar and native menus (instance/shell/, tab-scroll.tsx, session list, lib/native/menu-labels*): dev-docs/UI_SHELL.md.
  • Session state and recovery (stores/session-state.ts, stores/session-generation-recovery.ts): dev-docs/SESSION_RECOVERY.md.
  • Dialogs, utility windows, icon toggles, surfaces and scrollbars (alert-dialog.tsx, dismissible-window.tsx, auth recovery, styles/utilities.css, index.css): dev-docs/UI_CONVENTIONS.md.
  • Settings and Preferences (settings rows/actions, Preferences window and project context, Providers/Web search, Stats, notifications, bug report): dev-docs/SETTINGS.md; provider accounts and usage dev-docs/PROVIDER_ACCOUNTS.md; hotkeys dev-docs/HOTKEYS.md; palettes dev-docs/PALETTE_SOURCES.md; plugin controls dev-docs/PLUGIN_CONTROLS.md; right-panel customization and panel extensions dev-docs/PANEL_EXTENSIONS.md.
  • Projects and tabs (closing tabs, temporary workspaces, new-instance launcher, Git-unavailable mode): dev-docs/PROJECTS.md.
  • Files panel and Git (Workspace/Changes/Commits, file watches, Git init, whitespace filter): dev-docs/FILES_PANEL.md.
  • Worktrees and event ownership (workspaces/native-worktrees.ts, workspaces/worktree-inventory.ts): dev-docs/WORKTREE_SESSION_PLACEMENT.md.
  • OpenCode runtime, setup, upgrades and OpenCode settings: dev-docs/OPENCODE_RUNTIME_SETUP.md; bundled plugin builds, provisioning, presence readiness, the event relay and the Design agent and skills (opencode/design/): dev-docs/OPENCODE_COMPATIBILITY.md; connection budget: dev-docs/CACHE_REFRESH_CONVENTIONS.md; session environment: dev-docs/SESSION_ENVIRONMENT.md; pruning: dev-docs/SESSION_PRUNING_RPC.md.
  • OpenCode integrations (opencode/integrations/, integration-types.ts; fixtures scripts/fixtures/fake-integration/, scripts/fixtures/fake-npm-registry.mjs): dev-docs/OPENCODE_INTEGRATIONS.md.
  • Remote Control and Remote Access settings: dev-docs/REMOTE_CONTROL.md; SideCars: dev-docs/architecture.md.
  • Browser previews and automation: dev-docs/BROWSER_AUTOMATION.md, dev-docs/BROWSER_DEVICE_EMULATION.md.
  • Desktop hosts: data profiles dev-docs/DESKTOP_DATA_PROFILES.md; updates and update feed dev-docs/TAURI_UPDATER.md; Tao/Tauri backports packages/tauri-app/vendor/README.md; bundled Node/npm dev-docs/RUNTIME_MAINTENANCE.md.
  • Public help (docs/help/, help entry points): dev-docs/USER_HELP.md.

Multi-Language Support (i18n)

Never hardcode user-visible strings. The UI uses a small custom i18n layer (packages/ui/src/lib/i18n/index.tsx).

  • Use useI18n() (const { t } = useI18n();) in components and tGlobal(...) in stores/non-component code; never import enMessages in feature code.
  • Messages are flat dot-key TypeScript objects ("flat.dot.keys": "string") in packages/ui/src/lib/i18n/messages/<locale>/, merged by each locale's index.ts via messages/merge.ts (duplicate keys throw at build time). Add a string to the right en/*.ts part file and the same key to every other locale's matching file: missing keys silently fall back to English, then the key.
  • Placeholders are simple {name} replacements (word characters only; never {file-name}); plurals use separate keys such as something.one/something.other, chosen in code.
  • A new language needs a messages/<locale>/ folder + index.ts, an entry in SUPPORTED_LOCALES (lib/i18n/index.tsx) and an option in components/locale-selector.tsx.
  • The selected locale is the locale app preference, persisted via the server config (default ~/.config/codenomad/config.yaml; config.json is migration input only).

File Length Guidelines (Highlight Only)

File size is a refactoring signal, never by itself a reason to refactor. When a change touches a source file over ~500 lines (target limit ~800) or a test file over ~1000, mention its path and approximate line count in your final response; keep new files under these thresholds unless there is a clear reason.

Tooling Preferences

  • Modify existing files with the edit tool; use write only to create new files.
  • Browser rendering regressions live in packages/ui/tests/browser/ (deterministic HTTP fixtures in fixtures/) and exercise the real Solid components and native event dispatcher, never reimplemented rendering logic. Run npm run test:browser --workspace @codenomad/ui after npx playwright install chromium; CODENOMAD_BROWSER_PATH may select an existing Chromium executable.
  • Concurrent Vite browser fixtures use tests/browser/fixture-cache.ts for per-server optimized-dependency caches; close the server before disposing its owned temporary cache. Never clear the checkout's shared cache to repair a fixture or make parallel tests share mutable optimizer output. The one sanctioned exception is the runner-owned fixture daemon (dev-docs/BROWSER_TESTING.md): each run spawns one daemon child that owns a single cache dir and serves read-only borrowers over loopback, stopping with an authenticated request when the run ends.

Desktop Runtime Launch

  • Native automation instrumentation starts automatically. Do not configure a fixed CDP port or a manual WebView2 profile.
  • Rebuild Electron before calling codenomad.act({ action: "restart" }). For Windows Tauri, stop and relaunch the release executable only when the linker cannot replace it; never stop the shared OpenCode daemon.

Pull Requests

  • A PR that changes user-visible behavior (labels, controls, steps, defaults, limitations) updates the affected help pages in the same PR: English first, then the nine translations using each locale's UI labels (dev-docs/USER_HELP.md). Help publishes from dev, and CI checks only its structure and links. Answer the non-blocking help-update-reminder.yml comment (English UI messages changed without docs/help) before merging: update the help, or confirm nothing user-facing is documented there.

Commit Message Guidelines

  • Commit messages: a concise conventional-style subject, then body paragraphs explaining why the change exists, the user-visible behavior change, the implementation approach, important edge cases or platform considerations, and the validation or tests that prevent regressions.