Thank you for your interest in contributing! Open Cowork is an open-source desktop AI agent app built with Electron, React, and TypeScript. This guide covers everything you need to get started.
Requirements
- Node.js 22 (matches CI)
- npm 10+
- macOS or Windows
Install
git clone https://github.com/OpenCoworkAI/open-cowork.git
cd open-cowork
npm install # also runs postinstall: downloads Node binaries + rebuilds native modulesCommon commands
| Command | Purpose |
|---|---|
npm run dev |
Start dev server (Vite + Electron) |
npm run lint |
ESLint over src/**/*.{ts,tsx} |
npm run format |
Prettier write |
npx tsc --noEmit |
Type-check without emitting |
npm run test |
Run Vitest |
npm run build |
Full production build |
src/
├── main/ # Electron main process
│ ├── claude/ # AI execution (agent-runner, model resolution, auth)
│ ├── config/ # electron-store, API keys, presets
│ ├── mcp/ # MCP server lifecycle (stdio / SSE / Streamable HTTP)
│ ├── session/ # Session CRUD, chat history
│ ├── tools/ # Tool execution dispatch
│ ├── db/ # SQLite schema and migrations
│ ├── sandbox/ # Lima (macOS) / WSL2 (Windows) isolation
│ ├── skills/ # Skill discovery and hot-reload
│ ├── remote/ # Feishu/Lark bot integration
│ └── schedule/ # Cron-like scheduled tasks
└── renderer/ # React frontend
├── components/ # UI components
├── hooks/ # Custom React hooks
├── store/ # Zustand state
├── i18n/ # i18next localization
└── styles/ # Tailwind + global CSS
Test files live in src/ alongside their source, or under tests/ at the root, mirroring the source path (e.g. src/main/mcp/foo.ts → src/tests/mcp/foo.test.ts).
- TypeScript strict mode — no implicit
any - ESLint + Prettier — 2-space indent; run
npm run lintandnpm run formatbefore pushing - React functional components with hooks only — no class components
- Tailwind CSS for all styling — no CSS modules, no inline style objects unless unavoidable
- Icons — use
lucide-react; do not add other icon libraries
Branch naming
main — stable releases
dev — integration branch (target for most PRs)
feature/<name> — new features
fix/<name> — bug fixes
Conventional Commits are enforced by commitlint + husky on every commit.
<type>(<scope>): <short summary>
Allowed types: feat, fix, refactor, perf, docs, test, build, chore, ci, style, revert, release, merge
Header max length: 100 characters
Examples:
feat(mcp): add Streamable HTTP transport support
fix(sandbox): handle WSL2 path with spaces
docs: update README setup instructions
test(session): add unit tests for session-manager
Scope is optional but encouraged.
- Target
devfor all feature/fix PRs; targetmainonly for releases. - Tests are required for every
featandfixPR — see Testing. - Single component file limit: keep individual component files under 500 lines. Split large components into smaller sub-components.
- No
any: useunknown+ type guards instead.catch (e: unknown)is correct;catch (e: any)will be rejected in review. - CI must be green: the PR must pass lint (
npm run lint), type-check (npx tsc --noEmit), and tests (npx vitest run) before merge. - Keep changes minimal and focused — avoid unrelated refactors in the same PR.
Open Cowork uses Dependabot (.github/dependabot.yml) to keep dependencies current. To avoid PR pile-up and reduce risk, we follow a tiered strategy:
| Tier | Scope | Merge policy |
|---|---|---|
| Auto-merge | GitHub Actions (all versions) | CI green → merge immediately. CI actions are grouped into a single PR. |
| Auto-merge | Dev-dependencies (patch + minor) | CI green → merge immediately. Grouped into a single PR per week. |
| Quick review | Production dependencies (patch) | Skim changelog, merge if CI green. Grouped into a single PR per week. |
| Manual review | Production dependencies (minor) | Read changelog, check for behavioral changes, then merge. Grouped into a single PR. |
| Dedicated branch | Any dependency (major) | Create a migration branch, test thoroughly, update code if needed. Never auto-merge. |
These packages are deeply integrated — any update (including patch) should be tested locally before merge:
electron— major upgrades need a dedicated migration branch; skip Dependabot for major versions@mariozechner/pi-coding-agent— core AI SDK; read release notes carefullybetter-sqlite3— native module; rebuild required, test on both platformsvite/@vitejs/plugin-react— build toolchain; verifynpm run buildsucceeds
- Monday: Dependabot opens grouped PRs
- Within the week: maintainer reviews and merges per tier policy
- Friday: any remaining patch/minor PRs should be merged or closed with reason
- Major upgrades: file an issue, plan the migration, merge when ready
Before adding a dependency:
- Check license — must be MIT, Apache-2.0, BSD, or ISC. No GPL/AGPL/SSPL.
- Check size — run
npx pkg-size <package>or check bundlephobia. Avoid bloating the installer. - Check maintenance — prefer packages with recent commits, multiple maintainers, and >1K weekly downloads.
- Prefer built-in — use Node.js built-ins or existing dependencies before adding new ones.
- Document why — add a comment in the PR description explaining why this dependency is needed and what alternatives were considered.
Open Cowork uses Vitest.
File placement
Place test files next to their source or under a mirrored path:
src/main/mcp/mcp-manager.ts → src/tests/mcp/mcp-manager.test.ts
src/main/session/session-manager.ts → src/tests/session/session-manager.test.ts
Both src/**/*.{test,spec}.ts and tests/**/*.{test,spec}.ts are picked up automatically.
Run tests
npm run test # watch mode
npx vitest run # single run (used in CI)
npx vitest run --coverage # with v8 coverage reportCoverage reports are written to coverage/ (html, json, text).
All user-visible strings must go through i18next — never hard-code display text.
// Good
import { useTranslation } from 'react-i18next';
const { t } = useTranslation();
return <button>{t('settings.save')}</button>;
// Bad
return <button>Save</button>;Translation files live in src/renderer/i18n/. Add keys to both en and zh locales when introducing new UI text.
Bug reports — use the GitHub issue template and include:
- Open Cowork version
- Operating system (macOS / Windows + version)
- Steps to reproduce
- Expected vs. actual behavior
- Relevant logs (from DevTools console or the in-app log viewer)
Feature requests — open a GitHub Discussion or issue with:
- The problem you are trying to solve
- Your proposed solution or behavior
- Any alternatives you considered
For questions or informal discussion, open a GitHub Discussion rather than an issue.