32 KiB
AgentCompany — CLAUDE.md
Project
AgentCompany is a cross-platform Electron desktop app that lets users create autonomous AI companies. A user provides a company name, description, goal, and deliverable. A CEO agent self-organizes other AI agents, delegates tasks, and the company runs end-to-end — producing code, content, research, and social media — while the human observes through a Slack-style hub.
Core Value: Zero-setup autonomous AI company — user enters a goal, agents self-organize and deliver.
Constraints
- Runtime: Electron with strict main/preload/renderer separation, contextIsolation enabled
- Database: SQLite (
node:sqlitebuilt-in), local-first, no external DB - Connectors: Claude Code, Codex, Gemini, Kimi CLI, OpenCode as first-class runtimes
- Platforms: macOS, Windows, Linux
- Security: No nodeIntegration in renderer, secrets via OS keychain, IPC validation on all channels
- Architecture: Service graph pattern in main process, typed IPC contracts, worker threads for execution
Electron Security Rules
contextIsolation: true,nodeIntegration: false,sandbox: truewhere feasible- Minimal preload bridge — renderer must never access Node.js APIs directly
- All IPC channels: typed, explicitly named, Zod-validated on the privileged side
- No hardcoded secrets, no arbitrary filesystem/shell/process access from renderer
- Agent tokens: signed JWT with agentId/companyId/runId, validated before any privileged action
Architecture
Three-tier process boundary:
- Main (
src/main/): Privileged Node.js — database, API server, services, IPC handlers, orchestration, OS integration - Preload (
src/preload/): Context-isolated bridge —DesktopApiviacontextBridge, 75+ typed IPC channels - Renderer (
src/renderer/): React 19 UI — components, hooks, i18n, formatters; calls only approved preload APIs
Key services in main: AppDatabase, ServiceGraph, OrchestrationService, AutomationService, WorkerService, ApiServer, BrowserActionService
Data flow: SQLite → IPC domain-changed events → renderer reloads snapshot. No client-side state library; React hooks + context only.
Result pattern: DesktopResult<T> = { ok: true, data: T } | { ok: false, error: { code, message } }. All IPC handlers return this.
Technology Stack
- Electron 39.8.0 / Node.js 22+ / TypeScript 5.9.3 / pnpm 10.24.0
- Build: electron-vite 5.0.0, Vite 7.0.0, electron-builder 26.8.1
- UI: React 19.2.4, TailwindCSS 4.2.1, Framer Motion 12.36.0, Phosphor Icons 2.1.10
- Validation: Zod 4.3.6 — schemas for all IPC payloads in
src/shared/contracts.ts - Logging: electron-log 5.4.3, Updates: electron-updater 6.8.3
- Testing: Vitest 4.1.0 (unit/integration), Playwright 1.58.2 (E2E)
- Adapters:
@agentcompany/adapter-{claude,codex,gemini,kimi,opencode}-local+adapter-utils
Database & Persistence
- SQLite at
{profileDir}/profile.sqlite— WAL mode, foreign keys, 25+ tables - Secrets:
SecretVaultwith{profileDir}/vault.key(600 permissions) - Logs:
{profileDir}/logs/, Artifacts:{profileDir}/artifacts/, Backups:{profileDir}/backups/ - Window state:
{profileDir}/window-state.json
Config & Env
AGENTCOMPANY_PROFILE_DIR(default:{userData}/profile)AGENTCOMPANY_UPDATE_URL,AGENTCOMPANY_ALLOW_INSECURE_VAULT,AGENTCOMPANY_DISABLE_UPDATES,AGENTCOMPANY_DISABLE_SINGLE_INSTANCE- Path aliases:
@shared→src/shared/,@main→src/main/,@renderer→src/renderer/,@preload→src/preload/
Monorepo
Root app + packages/adapter-{claude,gemini,codex,kimi,opencode}-local/ + packages/adapter-utils/. Defined in pnpm-workspace.yaml.
Conventions
Naming
- Files: kebab-case (
connector-auth-service.ts), React components: PascalCase (CompanyOnboarding.tsx) - Functions: camelCase with descriptive verbs (
saveCompany(),handleApprovalResolved()) - Variables: camelCase, booleans prefixed
is/has, collections plural - Types: PascalCase, DB entities suffixed
Record(CompanyRecord), schemas suffixedSchema - Constants: UPPERCASE for true constants (
BOARD_READER_ID), camelCase for derived (IPC_CHANNELS)
Patterns
- ES modules only (
import, norequire);import typefor type-only imports - Named exports preferred; default exports only for React components
- Error handling: Zod validation at IPC boundary →
fail()for errors, never throw across process boundary - React: functional components + hooks, Context for i18n,
useFocusTrap()/useReducedMotion()for a11y - Database: class-based
AppDatabase, direct SQL with placeholders, sync operations - IPC:
ipcRenderer.invoke()→DesktopResult<T>, handler validates with Zod then checks company ownership - No
console.log()in production — useelectron-log
Code Style
- 2-space indentation, ESLint 9 with
@typescript-eslintflat config - TypeScript strict mode,
anyallowed selectively (DB interop) - Comments only for non-obvious logic; rely on clear naming and types
Desktop UX Requirements
- Desktop-native UI: resizable windows, min sizes, keyboard-first, hover/focus states, context menus, drag-and-drop, clipboard, native menus
- Platform-aware: modifier keys, window chrome, tray behavior, file paths, notifications per OS
- Accessibility: keyboard nav, focus visibility, color contrast, reduced motion, semantic roles, ARIA labels
- Performance: responsive startup, no renderer blocking, worker threads for heavy work, minimal re-renders
Build & Release
- Clean old build and update version number before each build; output under
/build - Platform targets: macOS (app bundle, signing/notarization), Windows (NSIS/.exe), Linux (AppImage)
- Debug code must not remain in release output
- Auto-update strategy via electron-updater when configured
GSD Workflow Enforcement
Before using Edit, Write, or other file-changing tools, start work through a GSD command so planning artifacts and execution context stay in sync.
Use these entry points:
/gsd:quickfor small fixes, doc updates, and ad-hoc tasks/gsd:debugfor investigation and bug fixing/gsd:execute-phasefor planned phase work
Do not make direct repo edits outside a GSD workflow unless the user explicitly asks to bypass it.
Developer Profile
Profile not yet configured. Run
/gsd:profile-userto generate your developer profile. This section is managed bygenerate-claude-profile-- do not edit manually.
Design Context
Users
Builders and operators who want to spin up autonomous AI companies without managing infrastructure. They arrive with a goal, expect the system to self-organize, and watch their AI workforce execute. They care about output quality and want to feel like they're running something real — not playing with a demo.
Brand Personality
Bold, futuristic, ambitious. AgentCompany is the command layer for the next era of work. The interface should project quiet authority — this is a serious tool that happens to do something extraordinary.
Emotional Goal
Professional pride. The user should feel "I built something real." The interface should reinforce that their AI company is a legitimate operation — not a toy, not a gimmick, but a functioning organization they orchestrated.
Aesthetic Direction
- Reference: Notion — content-first layout, gentle hierarchy, flexible workspace feel
- Accent: Steel slate (#4a5d7a light, #7b9cc4 dark) — formal, authoritative, professional
- Theme: Full light + dark mode via CSS custom properties
- Typography: System sans-serif for UI, JetBrains Mono for code/data
- Icons: Phosphor (regular + fill weights), 16-18px standard
- Motion: Framer Motion with cubic-bezier(0.16, 1, 0.3, 1), reduced-motion aware
Anti-References (what this must NOT be)
- Not toy/demo: No cartoon illustrations, rainbow gradients, or playful AI mascots
- Not enterprise bloat: No overwhelming dashboards, feature overload, or Salesforce-style complexity
- Not generic SaaS: No cookie-cutter component libraries, stock photo energy, or bland templates
- Not sci-fi gimmick: No glowing neon, Matrix terminals, or over-the-top futuristic theming
Design Principles
- Content over chrome — Information density is a feature. Every element earns its place. No decorative filler.
- Quiet authority — The interface should feel confident without shouting. Subtle borders, restrained color, generous whitespace.
- Real, not theatrical — Agent activity should feel like watching a real company operate, not a sci-fi simulation. Status over spectacle.
- Desktop-native craft — Keyboard-first, focus rings, platform-aware shortcuts, proper window management. No web-app-in-a-wrapper feel.
- Accessible by default — Reduced motion, color contrast, semantic HTML, focus traps. Not an afterthought.
Project
AgentCompany — Match Paperclip Quality Milestone
AgentCompany is a cross-platform Electron desktop app that lets users create autonomous AI companies. A user provides a company name, description, goal, and deliverable. A CEO agent self-organizes other AI agents, delegates tasks, and the company runs end-to-end while the human observes through a Slack-style hub. This milestone closes the quality gap with the Paperclip reference implementation — bringing agent skill injection, task execution integrity, budget enforcement, session management, and UI maturity to production quality.
Core Value: Agents produce real, usable output — not garbage. Every run has domain knowledge (skills), validated tasks, quality gates on output, cost controls, and session continuity.
Constraints
- Runtime: Electron with strict main/preload/renderer separation — no architectural changes
- Database: SQLite (
node:sqlite) — implement all features within SQLite's capabilities - Adapters: Preserve existing 5-adapter modular npm package structure — extend, don't replace
- Backward compatibility: Existing companies/agents/tasks must continue to work after migration
- Performance: Skill injection must not add >2s to run startup; IPC events must be <100ms
Technology Stack
Languages
- TypeScript 5.9.3 - All application code (main, preload, renderer, shared, packages)
- JavaScript - Build scripts and some config files
- Python - Asset generation scripts (
scripts/generate-icons.py)
Runtime
- Electron 39.8.0 - Cross-platform desktop framework
- Node.js 22+ - Server runtime (main process)
- pnpm 10.24.0
- Lockfile:
pnpm-lock.yaml(present)
Frameworks
- Electron 39.8.0 - Desktop runtime with IPC, main/preload/renderer architecture
- React 19.2.4 - UI framework in renderer process
- TailwindCSS 4.2.1 - Utility-first CSS in renderer
- Zustand 5.0.12 - Lightweight state management (renderer)
- Immer 11.1.4 - Immutable state updates
- Framer Motion 12.36.0 - Animation and motion primitives in React components
- Vite 7.0.0 - Module bundler and dev server
- electron-vite 5.0.0 - Vite config wrapper for Electron main/preload/renderer
- @vitejs/plugin-react 5.0.0 - React JSX support in Vite
- @tailwindcss/vite 4.2.1 - TailwindCSS Vite integration
- Vitest 4.1.0 - Unit/integration test runner (Node environment)
- @playwright/test 1.58.2 - E2E testing framework (
tests/e2e/playwright.config.ts) - ESLint 9.38.0 - Code linting with flat config
- @typescript-eslint 8.46.1 - TypeScript linting support
- eslint-plugin-react-hooks 7.0.0 - React hooks rule enforcement
- eslint-plugin-react-refresh 0.4.24 - Fast refresh support
- TypeScript 5.9.3 - Type checking (
pnpm typecheck)
Key Dependencies
- zod 4.3.6 - Schema validation at IPC boundaries (main, preload, renderer share contracts)
- electron-log 5.4.3 - Structured logging in main process (no console.log in production)
- electron-updater 6.8.3 - Auto-update via electron-updater (when configured)
- node:sqlite - Built-in SQLite bindings for local database (no external DB driver)
- electron.safeStorage - OS keychain integration for credential encryption
- @phosphor-icons/react 2.1.10 - Icon library (16-18px standard)
- @tanstack/react-virtual 3.13.23 - Virtual scrolling for large lists
- clsx 2.1.1 - Conditional className utility
- tailwind-merge 3.5.0 - TailwindCSS className merging
- @fontsource-variable/inter - System sans-serif for UI
- @fontsource-variable/jetbrains-mono 5.2.8 - Monospace for code/data display
- @fontsource/instrument-serif - Serif font support
- @agentcompany/adapter-claude-local - Claude Code CLI adapter (workspace:*)
- @agentcompany/adapter-codex-local - Codex CLI adapter (workspace:*)
- @agentcompany/adapter-gemini-local - Gemini CLI adapter (workspace:*)
- @agentcompany/adapter-utils - Shared adapter utilities (workspace:*)
Configuration
- Files:
electron.vite.config.ts,tsconfig.json,vitest.config.ts,tests/e2e/playwright.config.ts - Profile directory:
{userData}/profile(default) orAGENTCOMPANY_PROFILE_DIRenv var - Database:
{profileDir}/profile.sqlite(WAL mode, foreign keys enabled) - Window state:
{profileDir}/window-state.json - Artifacts:
{profileDir}/artifacts/ - Logs:
{profileDir}/logs/ - Backups:
{profileDir}/backups/ - Secrets vault:
{profileDir}/vault.key(600 permissions) electron.vite.config.ts- Main/preload/renderer entry points and aliaseselectron-builder.yml- Platform-specific build targets (macOS dmg/zip, Windows NSIS/portable, Linux AppImage/deb/rpm)tsconfig.json- Path aliases:@shared,@main,@renderer,@preloadeslint.config.mjs- ESLint 9 flat configpnpm-workspace.yaml- Monorepo withpackages/*
Platform Targets
- Formats: dmg (installer), zip (portable)
- Architectures: x64, arm64
- Signing:
hardenedRuntime: true, Gatekeeper assessment disabled - Code sign config via:
CSC_LINK,CSC_KEY_PASSWORDenv vars - Formats: NSIS (installer), portable exe
- Architectures: x64, arm64
- Code sign config via:
WIN_CSC_LINK,WIN_CSC_KEY_PASSWORDenv vars - NSIS: oneClick false, perMachine false, allow custom install dir
- Formats: AppImage, deb, rpm, snap
- Architectures: x64, arm64 (AppImage/deb/snap); x64 (rpm)
- Desktop category: Development
- deb dependencies: libgtk-3-0, libnotify4, libnss3, libxss1, libxtst6, xdg-utils, libatspi2.0-0, libuuid1, libsecret-1-0
- Snap plugs: default, removable-media
Monorepo Structure
packages/adapter-claude-local/- Claude Code CLI integrationpackages/adapter-codex-local/- Codex CLI integrationpackages/adapter-gemini-local/- Gemini CLI integrationpackages/adapter-kimi-local/- Kimi CLI integration (not bundled in main build)packages/adapter-opencode-local/- OpenCode CLI integration (not bundled in main build)packages/adapter-utils/- Shared adapter types and utilities
Key Scripts
- Main:
out/main/index.js+out/main/worker.js(entry points in electron.vite.config.ts) - Preload:
out/preload/index.js(CJS format, chunked) - Renderer:
out/renderer/(Vite SPA bundle) - Desktop installers:
build/release/(platform-specific per electron-builder.yml)
Adapter System
execute()- Run code in CLI sessionsessionCodec- Serialize/deserialize session statetestEnvironment()- Check CLI availabilitymodels- List available models
Conventions
Naming Patterns
- kebab-case for all source files:
connector-auth-service.ts,ipc-core-handlers.ts,automation-service.ts - React components: PascalCase when exporting components:
RuleEditor.tsx,CompanyOnboarding.tsx - Test files: kebab-case with
.test.tsor.spec.tssuffix:database.test.ts,autonomous-chain.spec.ts,notification-service.test.ts - camelCase with descriptive verbs:
saveCompany(),handleApprovalResolved(),checkoutTask(),wakeAgentIfPossible() - Event handlers: prefix with
handleoron:handleSave(),handleTaskCreated(),onClick() - Prefix boolean-returning functions with
isorhas:isAgentPendingApproval(),hasCompany(),belongsToCompany() - camelCase for all variables:
companyId,workspaceId,agentId,tempDir - Boolean variables prefixed with
is,has, orcan:isEditing,hasError,canApprove - Collections in plural form:
agents,tasks,workspaces,tempDirs - PascalCase for all types:
AppDatabase,DesktopResult<T>,CompanyRecord,AgentRecord - Database entity types suffixed with
Record:CompanyRecord,AgentRecord,TaskRecord,ApprovalRecord,RunRecord - Zod schemas suffixed with
Schema:companyInputSchema,connectorInputSchema,workspaceInputSchema,approvalDecisionSchema - Generic types:
DesktopResult<T>for IPC return types,RuleFormStatefor form state interfaces - UPPERCASE for true constants defined at module level:
BOARD_READER_ID,ACCENT,LINE - camelCase for derived constants/configs:
IPC_CHANNELS,sidebarNavDefs,defaultRuleForm
Code Style
- 2-space indentation (enforced by ESLint configuration)
- No Prettier config in repository — style guided by ESLint rules
- Line length: no hard limit enforced, but prefer reasonable wrapping
- Semicolons: required (enforced by
@typescript-eslintdefaults) - ESLint 9 with flat config in
eslint.config.mjs - TypeScript ESLint rules enabled in recommended configuration
@typescript-eslint/no-explicit-anyset tooff—anyis allowed for database interop and bridge code@typescript-eslint/no-unused-vars: warn with patterns^_for unused parameters/variables- Unused variables can be ignored by prefixing with underscore:
_event,_prevStatus - React Hooks:
exhaustive-depsset to warn (not error), allowing intentional deviations - ESLint covers:
src/**/*.{ts,tsx},tests/**/*.{ts,tsx},scripts/**/*.{ts,mjs},packages/**/*.{ts,tsx} - Excluded:
node_modules/,out/,build/,dist/,coverage/,playwright-report/,test-results/
Import Organization
@shared/*→src/shared/— Zod schemas, types, contract definitions, localization@main/*→src/main/— Database, services, IPC handlers, API server@renderer/*→src/renderer/— React components, hooks, UI utilities@preload/*→src/preload/— Context-isolated bridge APIs- Use named exports for all utilities, services, handlers, and hooks
- Default exports only for React components (required for route-based splitting patterns)
- Example:
export function saveCompany()notexport default saveCompany - Example:
export default function CompanyOnboarding()for React components - Use
import typeexclusively for TypeScript-only imports to enable proper tree-shaking - Example:
import type { ProfileSnapshot, DesktopEvent } from "@shared/types";
Error Handling
- All IPC handlers return
DesktopResult<T>={ ok: true, data: T } | { ok: false, error: { code, message } } - Use helper functions
ok(data)andfail(code, message)fromipc-core-common.ts - Example from
ipc-core-admin-handlers.ts: - Zod is used for all IPC payloads:
const parsed = companyInputSchema.parse(payload); - Zod parsing happens at the IPC boundary (main process side)
- Parse before any business logic, catch validation errors and return
fail()with descriptive message - Example:
const parsed = approvalDecisionSchema.parse(payload); - All entity operations check company ownership with
ensureCompanyExists()andbelongsToCompany() - Pattern from
ipc-core-operations-handlers.ts: - Never throw exceptions across IPC. Always catch and return
fail(code, message) - Main ↔ Renderer communication must use
DesktopResultenvelope - Database errors are caught and wrapped:
catch (error) { return fail("APPROVAL_INVALID", error instanceof Error ? error.message : "...") } - Use SCREAMING_SNAKE_CASE for error codes:
INVALID_COMPANY_ID,CONNECTOR_COMMAND_LOCKED,TASK_NOT_FOUND,APPROVAL_NOT_FOUND - Error codes are used by renderer to determine UI response (e.g., showing specific error message)
Logging
- No
console.log()in production code. Useelectron-loginstead. - Logger injected as dependency to services:
logger: { info, error } - Example from
notification-service.test.ts: - Critical events: service initialization, crashes, recoveries
- Errors: validation failures, database errors, connectivity issues
- Debug: trace flow through complex orchestration (in dev mode)
Comments
- Only for non-obvious logic or business rules
- Prefer clear naming and types over comments
- Example: comments explaining why a decision was made, not what the code does
- Minimal use — TypeScript types are the primary documentation
- Use JSDoc for public APIs and exported functions if return type is complex
- Example for complex types:
Function Design
- Use object parameters (destructuring) for >3 parameters
- Example:
saveAgent({ companyId, name, role, ... }) - Avoid parameter lists with many flags
- Explicit return types for all exported functions
- Return early for error conditions:
if (error) return fail("CODE", "message"); - Consistent use of
DesktopResult<T>for IPC handlers - Use
async/await, not promises chains - Always handle errors in handlers:
try/catcharound database calls - Example pattern:
Module Design
- Named exports for utilities, services, handlers
- Default exports ONLY for React components
- Example good pattern:
export function registerCoreAdminHandlers({ ... }) - Used in
src/renderer/components/for organizing imports - Example:
export { AgentCreator, AgentEditor, AgentRoster } from "./..." - Database and major services are class-based (e.g.,
AppDatabase,ServiceGraph) - Other services are functional:
createNotificationService(),createEventBatcher() - Classes own initialization (constructor) and lifecycle (init/close methods)
React-Specific Patterns
- All React components are functional with hooks
- No class components
- Example:
export function RuleFormModal({ open, editingRule, companyId, onClose, onSaved }: Props) useCallback()for stable function references passed to event handlersuseEffect()for side effects with proper dependency arraysuseMemo()for expensive calculations and string translations- Example from
RuleEditor.tsx: - Zustand store (
useAppStore) for global UI state (sidebar collapsed, selected entities, locale) - Local
useState()for component-specific form state - No Redux, Context API used only for i18n provider
- Explicit interface or inline type for all props
- Example:
function RuleFormModal({ open, editingRule, companyId, onClose, onSaved }: { open: boolean; editingRule: AutomationRuleRecord | null; ... })
Architecture
Pattern Overview
- Process boundary enforcement: main (Node.js) → preload (context-isolated) ← renderer (React)
- Service graph: loosely-coupled async services coordinated by bootstrap
- Data flow: SQLite → IPC domain-changed events → Zustand store → React UI
- Agent execution: orchestration service queues runs to worker process (child utility process)
- Automation: event-driven triggers (task created, status changed, approval resolved) dispatch workflows
- IPC pattern:
ipcRenderer.invoke()→ Zod validation → DesktopResult pattern
Layers
- Purpose: Database operations, service coordination, IPC handler registration, external API communication, worker management
- Location:
src/main/ - Contains: Database class, service factories, IPC handlers, agent orchestration logic, API server, automation rules
- Depends on: Electron main process APIs, SQLite, node:fs, child processes via worker service
- Used by: Preload process (via ipcMain handlers), worker process (via message passing)
- Purpose: Context-isolated bridge exposing minimal DesktopApi to renderer via contextBridge
- Location:
src/preload/index.ts - Contains: ~75 typed IPC channel invocations, subscription to desktop events
- Depends on: Electron contextBridge, ipcRenderer, shared contracts
- Used by: Renderer process (via window.agentCompany global)
- Purpose: Display company state, handle user interactions, visualize agent execution
- Location:
src/renderer/ - Contains: React components, Zustand store (no Redux/Redux-like), hooks, i18n context, UI utilities
- Depends on: React 19, window.agentCompany preload API, Zustand, Framer Motion
- Used by: User directly through Electron window
- Purpose: Execute agent commands in isolated child process (Electron utilityProcess)
- Location: Built from agent adapters in
packages/adapter-*/ - Contains: Connector CLI execution, run log streaming, status reporting
- Depends on:
EnqueueRunPayloadmessage contract, agent connector CLIs (Claude, Codex, Gemini, Kimi, OpenCode) - Used by: Worker service via message passing
Data Flow
- Zustand store in
src/renderer/state/store.tsholds: - No Redux, no global context beyond locale/translation
- Derived state computed via hooks (e.g.,
selectedAgent = agents.find(a => a.id === selectedAgentId)) - Snapshot updates trigger full re-computation (no partial updates)
Key Abstractions
- Purpose: All SQLite operations, snapshot generation, business logic for data consistency
- Examples:
src/main/database.ts - Pattern: Class with ~100 public methods, synchronous SQLite.DatabaseSync, no ORM
- Responsibilities: CRUD for all entities, filtering/searching, metrics calculation, backup/restore, secret vault integration
- Purpose: Dependency injection and lifecycle management for 9 coordinated services
- Examples:
src/main/service-graph.ts - Pattern: Factory function returning object with service getters, lazy initialization via
init() - Services: DesktopShell, ConnectorHealth, Worker, Orchestration, Automation, Onboarding, BrowserAction, Updater, AppLifecycle
- Purpose: Agent task execution, workspace resolution, budget tracking, run queuing
- Examples:
src/main/orchestration-service.ts - Pattern: Factory with internal state (heartbeat timer, run cache), public methods for task/agent operations
- Coordinates with: Worker service (enqueue), Automation service (dispatch on status change), Database (persist)
- Purpose: Event-driven trigger evaluation and workflow execution
- Examples:
src/main/automation-service.ts - Pattern: Factory managing active execution state, async/await for workflow steps
- Triggers: task.created, task.status_changed, approval.resolved, comment.posted, document.created, run.completed
- Actions: assign_task, notify_agent, send_message, create_approval, trigger_heartbeat, escalate, cross_department_notify, auto_approve
- Purpose: Electron window lifecycle, platform integration, keyboard shortcuts, native menus
- Examples:
src/main/desktop-shell-service.ts - Pattern: Factory managing BrowserWindow instance, event listeners for menu/shortcut actions
- Responsibilities: window creation, state persistence, platform-specific behaviors
- Purpose: Child process lifecycle, run execution, log streaming
- Examples:
src/main/worker-service.ts - Pattern: Factory managing Electron utilityProcess, retry logic, consecutive wake detection
- Message types: enqueue-run (inbound), run-log/run-status/run-finished (outbound)
- Purpose: Handler registration, payload validation, sender URL verification, error sanitization
- Examples:
src/main/ipc-support.ts - Pattern: Factory with
registerHandle()method for each channel, returnsDesktopResult<T> - Security: Verifies senderFrame.url matches trusted renderer origin (dev or app://-) before processing
Entry Points
- Location: Electron main configuration in
electron.vite.config.tsorbuild/entry - Triggers: App launch via
electron .or packaged app - Responsibilities: Create main runtime, await bootstrap, setup single-instance lock, handle app lifecycle events
- Location:
src/renderer/main.tsx(React root) - Triggers: Main process creates BrowserWindow pointing to renderer dist
- Responsibilities: Mount React App component, initialize Zustand store, hydrate snapshot on first load
- Location:
src/main/ipc-core-handlers.tsdispatches to specialized handler modules - Handlers split across:
ipc-core-read-handlers.ts,ipc-core-operations-handlers.ts,ipc-core-work-graph-handlers.ts,ipc-agent-coordination-handlers.ts, etc. - Each handler: validates input with Zod, calls DB or service method, returns DesktopResult, publishes domain-changed on write
Error Handling
- IPC validation: Zod schema parsing at handler entry →
sanitizeHandlerError()converts ZodError toIPC_INVALID_PAYLOAD - DB errors: Throws logged to electron-log, caught by IPC handler, returned as DesktopResult error
- Worker errors: Run status set to "failed" with errorMessage, logged to run log file
- Automation errors: Try-catch blocks log errors but continue processing other rules
- Async cleanup:
appLifecycleServicewaits 3 seconds for worker child process to exit before app.exit(0)
Cross-Cutting Concerns
核心原则 (Core Persona)
- 第一性原理: 从原始需求出发。动机不清立刻停,路径非最优直接纠正。
- 极简沟通: 用简单直白的中文一次性输出,把用户当高中生。拒绝角色扮演,拒绝分段分口吻,对话中已解决的问题后续绝不再提。不要用 P0/P1/P2 这种术语。
- Let it crash: 发现问题尽早暴露。严禁使用任何降级、兜底、后发式补丁或非严谨通用算法的后处理补救。
- 禁止擅自开分支: 严禁私自创建新 worktree。可以给建议,但必须征得用户明确同意后方可操作。
- 自检与精简: 每次改动后,严格执行「Review查Bug然后第一性原理分析」流程,思考是否有更简单、更稳健的实现。
开发工作流 (Development Workflow)
- 分析层: 文字、图标、颜色的UI修改,直接操作执行层并落地archive。重大重构/多任务才走规划层。
- 规划层: 使用 using-superpowers 编排流程并产出/更新全局流程图。
- 任务层: 使用 planning-with-files 维护 task_plan.md / progress.md / findings.md。
- 执行层: OpenSpec 四步闭环(propose -> 用户确认 -> apply -> archive)。
- 粒度控制: 动手前用 gsd-method-guide 拆解为
<files>/<action>/<verify>/<done>。
工程规范 (Engineering Constraints)
- 数据处理: 不可捏造数据。生产代码严禁 Mock。Mock 仅限本地调试(统一入口:
127.0.0.1:xxxx/mock),必须在.gitignore中排除。 - 自动化执行:
curl、cat、git等命令直接运行免确认;Playwright 脚本在终端持续会话,禁止无意义的暂停。 - 子代理分流: 复杂问题(多于1个、需 Review/研究/并行分析)必须拆解并使用子代理(5.4 模型),保持主上下文纯净。
- API 接入: 参考
/Users/ifengz/CodingCase/002_DevelopSpec/1.Doc/中的现成方案,并不断补充新内容。 - 自我进化: 用户指正后立即更新
lessons.md。开始新任务前必须回顾lessons.md。
运维安全守则 (Operations Constraints)
- 排障顺序: 遇网络/证书/代理异常,优先排查入口及反代配置。严禁使用临时IP:端口判定数据库损坏,必须寻找固定入口(域名/面板地址)。
输出规范 (Output Specs - 拒绝啰嗦)
- 禁止陈述式汇报: 严禁复读背景,严禁分“证据/分析/结论”等多维度拆解简单问题。
- 结论先行: 直接给结论和修补方案。解释必须是短小精悍的中文大白话,不显示P0/P1等级。
- 表格化输出: 多数内容(尤其是评审、对比、多项任务)必须以Markdown表格输出。
- 强制收口: 结束对话必须明确告知用到的 skill。