Development guidelines for Witsy, a cross-platform Electron-based desktop AI assistant with multi-LLM support, MCP client capabilities, and automation features.
Development guidelines for contributing to Witsy, a cross-platform desktop AI assistant built with Electron, TypeScript, Vue 3, and Vite.
Witsy is a universal MCP (Model Context Protocol) client that integrates multiple LLM providers and supports:
**Main Process** (`src/main/`): Electron main process handling system integration, IPC, and native APIs
**Renderer Process** (`src/renderer/`): Vue 3 frontend with Vite bundling
**Preload Scripts** (`src/preload.ts`): Secure IPC bridge between main and renderer
**LLM Integration** (`src/renderer/services/llms/`): Multi-provider abstraction using `multi-llm-ts`
**Plugin System** (`src/renderer/services/plugins/`): Extensible tools for search, filesystem, python execution
**Automation** (`src/main/automations/`): Cross-platform automation for AI commands
ALWAYS work in small increments following this cycle:
1. Implement a small piece of functionality
2. Run linting: `npm run lint`
3. Write/update tests immediately
4. Verify tests pass: `npm run test:ai`
5. Confirm with user before moving to next task
**Critical Rules:**
Run `npm run lint` to check code quality and Vue type errors. No output means code is properly formatted with no errors. This is MANDATORY before running tests.
CSS variables are validated with Stylelint: `npm run lint:css` checks that all `var(--...)` references use defined variables from `css/variables.css` and `css/index.css`.
**Unit Tests:**
```bash
npm run test:ai -- <test-name-or-path> # Run specific test
npm run test:ci # With coverage
```
**Test Pattern Priorities:**
1. Test user interactions via HTML events (trigger, setValue)
2. Check state updates in UI or store
3. Avoid directly injecting data into Vue `vm` or calling methods
4. Use `await nextTick()` for UI updates (avoid artificial waits)
5. Only use `vi.waitFor`/`vi.waitUntil` when absolutely necessary with reasonable timeouts
**IPC Mocking:**
```typescript
import { useWindowMock } from '@tests/mocks/window'
// Use windowMock in beforeAll or beforeEach
```
**Coverage Analysis:**
```bash
node tools/coverage_gaps.js # Top 20 files with most uncovered lines
node tools/coverage_gaps.js --limit 10 # Top 10 files
node tools/coverage_gaps.js --filter src/components # Filter by directory
node tools/coverage_gaps.js --show-lines # Show uncovered line numbers
```
This identifies files with the most absolute uncovered lines (not percentages), helping prioritize testing efforts.
```typescript
import { store } from '@services/store'
// Vue 3 reactive object holding app state, preferences, conversations
```
```typescript
// Centralized in src/types/config.ts
export type Configuration = {
engines: Record<string, EngineConfig>, // LLM provider configs
plugins: Record<string, PluginConfig>, // Plugin settings
// ... other sections
}
```
**IPC Events (main↔renderer):**
```typescript
import useIpcListener from '@composables/ipc_listener'
const { onIpcEvent } = useIpcListener()
onIpcEvent('docrepo-modified', (data) => { /* handle */ })
// Handlers auto-clean on component unmount
```
Main process uses: `emitIpcEvent`, `emitIpcEventToAll`, `emitIpcEventToFocused`
**Bus Events (renderer↔renderer):**
```typescript
import useEventBus from '@composables/event_bus'
const { onBusEvent, emitBusEvent } = useEventBus()
onBusEvent('fullscreen', (data) => { /* handle */ })
emitBusEvent('new-chat', payload)
```
Use for cross-branch component communication. Prefer Vue emit/provide-inject for parent-child.
Constants organized in `src/ipc_consts.ts`:
```typescript
export const CHAT = {
STREAM: 'chat-stream',
CANCEL: 'chat-cancel'
} as const
```
Main handlers: `src/main/ipc.ts`
Preload exposures: `src/preload.ts`
If `window.api.*` causes lint errors, add method signature to:
```typescript
// src/types/index.ts
declare global {
interface Window {
api: {
// Add your method here
}
}
}
```
Globally available CSS:
**IMPORTANT:** Always use globally defined CSS variables. Do not create custom styles or hardcoded values. All CSS variables are defined in `./css/index.css`.
Uses `vue-i18n`. Translations in `./locales/*.json`.
```typescript
// In renderer process
import { t } from '@services/i18n'
```
Only add English translations when creating features. For other languages, discuss with team before running `./tools/i18n_check.ts --fix`.
Leave a review
No reviews yet. Be the first to review this skill!
# Download SKILL.md from killerskills.ai/api/skills/witsy-ai-assistant-development/raw