Guidelines for AI coding agents working in this repository.
packages/
ui-components/ @react-trace/ui-components — Kbd, Tooltip, Button, IconButton,
PanelHeader, Popover, DropdownMenu,
icons (via @hugeicons/core-free-icons)
core/ @react-trace/core — Trace component, plugin API, utilities
plugin-preview/ @react-trace/plugin-preview — Monaco editor action panel, FS access
plugin-comments/ @react-trace/plugin-comments — inline comments + Send to OpenCode
plugin-copy-to-clipboard/ @react-trace/plugin-copy-to-clipboard
plugin-open-editor/ @react-trace/plugin-open-editor
react-trace/ @react-trace/kit — batteries-included convenience wrapper
apps/
example/ Vite + React demo app
Toolchain: pnpm workspaces · Turborepo · tsdown (rolldown bundler) · TypeScript · oxlint · oxfmt · vitest
pnpm build # build all packages in dependency order
pnpm dev # watch mode (builds deps first, then watches)
pnpm typecheck # tsc --noEmit across all packages
pnpm lint # oxlint across all packages
pnpm fmt # oxfmt . (auto-fix formatting)
pnpm fmt:check # check formatting without writing
pnpm test # vitest run across all packagespnpm --filter @react-trace/core build
pnpm --filter @react-trace/plugin-comments typecheck
pnpm --filter @react-trace/core testpnpm --filter @react-trace/core exec vitest run src/path.test.tspnpm --filter example dev # start dev server
pnpm --filter example build # production build (uses prod stubs — see below)Every package has src/index.prod.ts — a zero-cost stub (all exports are no-ops).
The package.json exports field uses "development" / "production" / "default" conditions.
apps/example/vite.config.ts uses resolve.alias to redirect imports to prod stubs in production mode.
Rule: When adding a new public export to a package, mirror it in src/index.prod.ts (as a type-only re-export or a no-op function).
strict: true,noUncheckedIndexedAccess: true— noany, no non-null assertions without reason- Target: ES2022, lib: ES2024 + DOM
moduleResolution: "Bundler"— no.jsextensions needed on imports- Use
typekeyword for type-only imports:import type { Foo } from './foo' - When a value and types come from the same module, mix inline:
import { fn, type Foo } from './foo' - Prefer
interfacefor object shapes that may be extended;typefor unions/aliases
Order (enforced by oxlint):
- External packages (
react,@monaco-editor/react, etc.) - Blank line
- Internal workspace packages (
@react-trace/core) - Blank line
- Local relative imports (
./store,../utils)
Always use named exports. Default exports only in react-trace/src/index.tsx (the convenience component).
- Formatter: oxfmt — run
pnpm fmtbefore committing. No manual whitespace decisions. - No CSS classes — all styling uses inline
styleobjects withReact.CSSProperties. - No Tailwind — inline styles only.
- Color palette:
- Background:
#18181b, surface:#09090b - Border:
#27272a, subtle border:#3f3f46 - Text primary:
#fafafa, secondary:#d4d4d8, muted:#71717a - Accent (blue):
#3b82f6, success (green):#22c55e, danger (red):#ef4444
- Background:
- No emojis in source code or comments.
- Avoid section separators in longer files like below (if you feel you need, better to refactor into multiple files instead):
// --------------------------------------------------------------------------- // Section name // ---------------------------------------------------------------------------
- Files:
PascalCase.tsxfor React components,camelCase.tsfor modules - Components:
PascalCase - Functions/variables:
camelCase - Interfaces/types:
PascalCase - Constants:
SCREAMING_SNAKE_CASEfor module-level primitives (e.g.LINE_HEIGHT,IS_MAC) - Plugin factory functions:
XxxPlugin()— returnsTracePlugin - Store files: module-level
let+ subscribe/getSnapshot/set pattern (compatible withuseSyncExternalStore)
Plugins implement TracePlugin:
{
name: string
toolbar?: ComponentType
actionPanel?: ComponentType
settings?: ComponentType
}toolbarrenders plugin-owned UI directly inside the core toolbar.actionPanelrenders plugin-owned UI directly inside the widget action panel. These components receive no props; read shared state through the public hooks.settingsrenders plugin-owned UI directly inside the widget settings popover.- The deprecated compatibility contract (
toolbarItems,actions,subpanel,ToolbarItem,Action) has been removed and should not be documented or used as supported API.
Shared hook surface from @react-trace/core:
useProjectRoot()— absolute project root from<Trace root="..." />useInspectorActive()— whether inspector mode is currently activeuseSelectedContext()— currently selected component contextuseSelectedSource()— currently selected source for action-panel flowsuseWidgetPortalContainer()— portal container inside the widget shell for tooltips, dropdowns, popovers, and other portal UIuseDeactivateInspector()— disable inspector mode before opening plugin-owned interactive UIuseClearSelectedContext()— clear the current selection when a plugin flow should dismiss it
Plugin-owned UI should render directly from toolbar, actionPanel, or settings. For popovers, dropdowns, tooltips, and other portal-mounted UI, use the widget portal container instead of rendering to document.body.
- Async fire-and-forget calls must have
.catch(() => {})— no silent unhandled rejections - In React components, prefer graceful degradation over throwing (return
nullif source is missing) try/catchin utility functions should return a sensible fallback, not re-throw
# External plugin (for third-party authors)
pnpm create react-trace-plugin
# Workspace plugin (for this monorepo)
pnpm create-plugin
# or: pnpm create-plugin -w --name my-feature --description "..." --slots toolbar,actionPanel,settingsThe CLI prompts for a plugin name, description, and which slots to scaffold (toolbar, actionPanel, settings), then generates a complete plugin package with build config, production stub, and README.
The CLI creates packages/plugin-xxx/ with all source files, but this manual step is still needed:
- Optionally wire into
packages/react-trace/src/index.tsxfor the convenience bundle
Read known files directly, and parallelize independent read-only inspection when possible. Use broader codebase search only when you do not yet know which files contain the information you need.