Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Project architecture and file structure conventions for all process types. Use when: (1) Creating new files or modules, (2) Deciding where code should go, (3) Converting single-file components to directories, (4) Reviewing code for structure compliance, (5) Adding new bridges, services, agents, or workers.
.claude/skills/iofficeai-architecture/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-02 | ✗→✓ | ▲ Improved | -7% | 0% |
| case-01 | ✗→✓ | ▲ Improved | 43% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 15% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 62% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 2% | 0% |
Determine correct file placement and structure for an Electron multi-process project.
Is it UI (React components, hooks, pages)?
└── YES → packages/desktop/src/renderer/ → see references/renderer.md
Is it an IPC handler responding to renderer calls?
└── YES → packages/desktop/src/process/bridge/ → see references/process.md
Is it business logic running in the main process?
└── YES → packages/desktop/src/process/services/ → see references/process.md
Is it an AI platform connection (API client, message protocol)?
└── YES → packages/desktop/src/process/agent/<platform>/
Is it a background task that runs in a worker thread?
└── YES → packages/desktop/src/process/worker/
Is it used by BOTH main and renderer processes?
└── YES → packages/desktop/src/common/
Is it an HTTP/WebSocket endpoint?
└── YES → packages/desktop/src/process/webserver/
Is it a plugin/extension resolver or loader?
└── YES → packages/desktop/src/process/extensions/
Is it a messaging channel (Lark, DingTalk, Telegram)?
└── YES → packages/desktop/src/process/channels/Hard rules — violating them causes runtime crashes.
| Process | Can use | Cannot use | | --------------------------------------------------- | ---------------------------------------------------------- | ----------------------------------------------- | | Main (packages/desktop/src/process/) | Node.js, Electron main APIs, fs, path, child_process | DOM APIs (document, window, React) | | Renderer (packages/desktop/src/renderer/) | DOM APIs, React, browser APIs | Node.js APIs (fs, path), Electron main APIs | | Worker (packages/desktop/src/process/worker/) | Node.js APIs | DOM APIs, Electron APIs | | Preload (packages/desktop/src/preload/) | contextBridge, ipcRenderer | DOM manipulation, Node.js fs |
Cross-process communication:
packages/desktop/src/preload/ + packages/desktop/src/process/bridge/*.tspackages/desktop/src/process/worker/WorkerProtocol.tstypescript// NEVER in renderer import { something } from '@process/services/foo'; // crashes at runtime // Use IPC instead const result = await window.api.someMethod(); // goes through preload
| Scope | Convention | Reason | | ---------------------------------- | ---------- | ------------------------------------------------------- | | Renderer component/module dirs | PascalCase | React convention — dir name = component name | | Everything else | lowercase | Node.js convention | | Categorical dirs (everywhere) | lowercase | components/, hooks/, utils/, services/ | | Platform dirs (everywhere) | lowercase | acp/, codex/, gemini/ — cross-process consistency |
> Quick test: "Inside packages/desktop/src/renderer/ AND represents a specific component/feature (not a category)?" → PascalCase. Otherwise → lowercase.
| Content | Convention | Examples | | ------------------------- | ------------------------------- | ------------------------------------- | | React components, classes | PascalCase | SettingsModal.tsx, CronService.ts | | Hooks | camelCase with use prefix | useTheme.ts, useCronJobs.ts | | Utilities, helpers | camelCase | formatDate.ts, cronUtils.ts | | Entry points | index.ts / index.tsx | Required for directory-based modules | | Config, types, constants | camelCase | types.ts, constants.ts | | Styles | kebab-case or Name.module.css | chat-layout.css |
index.tsx.pages/<PageName>/. Promote to shared only when a second consumer appears.Tests mirror source files in tests/ subdirectories:
| Source | Test | | ------------------------------------------------------------ | ----------------------------------------------- | | packages/desktop/src/process/services/CronService.ts | tests/unit/cronService.test.ts | | packages/desktop/src/renderer/hooks/ui/useAutoScroll.ts | tests/unit/useAutoScroll.dom.test.ts | | packages/desktop/src/process/extensions/ExtensionLoader.ts | tests/unit/extensions/extensionLoader.test.ts |
When tests/unit/ exceeds 10 direct children, group into subdirectories matching source structure.
preload.tsindex.tsx / index.ts entry pointpages/<PageName>/, not in shared dirsvitest.config.ts → coverage.exclude| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-02 | fail→pass | 18,329 | 8,361 | -54% | 1 | 1 | 0% | 3,730 | 3,460 | -7% | 0 | 0 | — |
case-01 | fail→pass | 10,784 | 5,812 | -46% | 1 | 1 | 0% | 1,908 | 2,721 | +43% | 0 | 0 | — |
case-03 | fail→fail | 11,930 | 7,310 | -39% | 1 | 1 | 0% | 2,279 | 3,108 | +36% | 0 | 0 | — |
case-04 | pass→pass | 10,080 | 10,424 | +3% | 1 | 1 | 0% | 1,929 | 3,689 | +91% | 0 | 0 | — |
case-05 | pass→pass | 6,487 | 4,439 | -32% | 1 | 1 | 0% | 1,269 | 2,424 | +91% | 0 | 0 | — |
case-06 | pass→pass | 3,160 | 1,677 | -47% | 1 | 1 | 0% | 542 | 1,847 | +241% | 0 | 0 | — |
case-07 | fail→pass | 11,276 | 4,072 | -64% | 1 | 1 | 0% | 2,056 | 2,364 | +15% | 0 | 0 | — |
case-08 | fail→pass | 9,041 | 5,660 | -37% | 1 | 1 | 0% | 1,613 | 2,621 | +62% | 0 | 0 | — |
case-09 | fail→pass | 12,012 | 3,517 | -71% | 1 | 1 | 0% | 2,114 | 2,152 | +2% | 0 | 0 | — |
case-10 | fail→pass | 9,883 | 4,173 | -58% | 1 | 1 | 0% | 1,891 | 2,291 | +21% | 0 | 0 | — |
case-11 | fail→pass | 10,884 | 3,193 | -71% | 1 | 1 | 0% | 1,976 | 2,170 | +10% | 0 | 0 | — |
case-12 | fail→pass | 8,628 | 2,438 | -72% | 1 | 1 | 0% | 1,622 | 2,037 | +26% | 0 | 0 | — |
case-13 | fail→pass | 7,860 | 4,080 | -48% | 1 | 1 | 0% | 1,511 | 2,338 | +55% | 0 | 0 | — |
case-14 | pass→pass | 7,976 | 2,878 | -64% | 1 | 1 | 0% | 1,466 | 2,042 | +39% | 0 | 0 | — |
case-15 | pass→pass | 10,767 | 2,344 | -78% | 1 | 1 | 0% | 1,826 | 1,995 | +9% | 0 | 0 | — |
case-16 | pass→pass | 9,086 | 2,925 | -68% | 1 | 1 | 0% | 1,713 | 2,069 | +21% | 0 | 0 | — |
case-17 | pass→pass | 10,172 | 4,797 | -53% | 1 | 1 | 0% | 1,867 | 2,506 | +34% | 0 | 0 | — |
case-18 | pass→pass | 9,783 | 3,722 | -62% | 1 | 1 | 0% | 1,716 | 2,257 | +32% | 0 | 0 | — |
case-19 | pass→pass | 13,439 | 9,764 | -27% | 1 | 1 | 0% | 2,467 | 3,400 | +38% | 0 | 0 | — |
case-20 | pass→pass | 9,337 | 2,658 | -72% | 1 | 1 | 0% | 1,483 | 1,957 | +32% | 0 | 0 | — |
case-21 | fail→pass | 8,660 | 3,811 | -56% | 1 | 1 | 0% | 1,506 | 2,245 | +49% | 0 | 0 | — |
case-22 | fail→pass | 7,624 | 2,248 | -71% | 1 | 1 | 0% | 1,362 | 2,005 | +47% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +50 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.