How to Contribute to the Openwork Project: A Complete Developer Guide
To contribute to Openwork, fork the repository on GitHub, install dependencies with pnpm install, launch the dev environment using pnpm dev, implement your feature in the relevant package, write end-to-end tests in evals/specs/, and submit a pull request against the dev branch.
Openwork is a modular, open-source platform maintained by different-ai that combines an Electron desktop client, a Node.js/TypeScript backend, and a cloud control plane called Den. This guide walks you through the exact steps to set up your local environment, navigate the monorepo architecture, and submit contributions that meet the project's quality standards.
Understanding the Openwork Architecture
Before writing code, familiarize yourself with the three-tier client-server-control-plane pattern. The codebase is organized as a monorepo using pnpm workspaces to share type-safe TypeScript utilities across packages.
Desktop UI (Electron + React): The user interface lives in packages/ui/ and renders inside an Electron shell. Key entry points include packages/ui/src/react/platform-detect.ts for OS/architecture detection and apps/ui-demo/vite.config.ts for the Vite development server configuration.
Server API (Node.js): The local backend in apps/server/src/ persists workspace data, manages plugins, and exposes the MCP (Multi-Capability Protocol). Critical files include apps/server/src/server.ts for booting the HTTP server and apps/server/src/workspaces.ts for workspace CRUD operations.
Den (Control Plane): This cloud-hosted layer handles model provisioning, team management, and policy enforcement. The bridge between your local server and Den is implemented in apps/server/src/cloud-plugins.ts, which forwards MCP calls to the remote endpoint at https://api.openworklabs.com/mcp/agent.
Setting Up Your Development Environment
Start by forking the repository and cloning your fork locally. Openwork requires pnpm for dependency management.
Install all dependencies from the repository root:
pnpm install
This command automatically links workspace packages between the UI and server, ensuring a single source of truth for shared types.
Running the Development Environment
Openwork provides two commands for local development. For standard development, run:
pnpm dev
This starts the Vite UI dev server on http://localhost:5173 and launches Electron with Chrome DevTools Protocol (CDP) access available on http://127.0.0.1:9223.
For isolated feature branch development, use:
pnpm dev:worktree
This creates a separate dev profile with isolated state, useful when working on parallel features without conflicts. For CI environments, the project also provides scripts/dev-headless-web.ts to launch a headless Electron instance.
Contributing Code: Step-by-Step Workflow
1. Implement UI Changes
Modify React components under packages/ui/src/. Reference packages/ui/src/react/platform-detect.ts for examples of cross-platform TypeScript patterns that detect OS and CPU architecture.
2. Extend Server Capabilities
Add routes or database models under apps/server/src/. The main entry point is apps/server/src/server.ts, where you wire new HTTP routes and MCP registrations.
3. Add New MCP Skills
To expose new capabilities to AI agents, define your skill in apps/server/src/skills.ts:
// apps/server/src/skills.ts
export const myNewSkill = {
name: "my-new-skill",
description: "Does something useful",
execute: async (input: any) => {
// your logic here
return { result: "done" };
},
};
Register the skill in the server entry point:
// apps/server/src/server.ts
import { myNewSkill } from "./skills";
mcp.registerSkill(myNewSkill);
4. Write End-to-End Tests
Openwork requires slow specs—full-stack tests using @openwork/testkit—to validate complete user scenarios. Place these in evals/specs/ using the .slow.test.ts suffix. This ensures the CI stays green and guarantees that hidden tests will pass.
Example test structure:
// evals/specs/my-new-skill.slow.test.ts
import { test, expect } from "@openwork/testkit";
test("my-new-skill works end-to-end", async ({ client }) => {
const result = await client.executeCapability("my-new-skill", { foo: "bar" });
expect(result).toMatchObject({ result: "done" });
});
Reference evals/specs/first-run-local.slow.test.ts for a complete example validating a fresh local installation.
5. Run the Test Suite
Verify your changes locally before submitting:
pnpm test # Runs unit tests
pnpm test:slow # Executes full-stack specs (uses Daytona when available)
All tests must pass before opening a pull request.
6. Submit Your Pull Request
Push your branch to your fork and open a PR against the dev branch. The CI automatically runs the test suite and generates a testkit evidence tape; ensure this tape is attached to your PR for human verification.
Key Source Files Reference
Keep these entry points bookmarked when navigating the codebase:
apps/server/src/server.ts– Backend entry point for HTTP routes and MCP registrationapps/server/src/skills.ts– Central registry for MCP-exposed capabilitiesapps/server/src/workspaces.ts– Workspace CRUD operations and data modelsapps/server/src/cloud-plugins.ts– Bridge to the Den control planepackages/ui/src/react/platform-detect.ts– Cross-platform detection utilitiesevals/specs/first-run-local.slow.test.ts– Example end-to-end test implementation
Summary
- Openwork uses a monorepo structure with pnpm workspaces linking the Electron UI, Node server, and shared types
- Run
pnpm devfor standard development orpnpm dev:worktreefor isolated profiles - Implement UI changes in
packages/ui/srcand server logic inapps/server/src - Register new MCP skills in
apps/server/src/skills.tsand expose them viaserver.ts - Write slow specs in
evals/specs/to validate full-stack functionality and satisfy hidden test requirements - Execute
pnpm testandpnpm test:slowlocally before submitting PRs to thedevbranch
Frequently Asked Questions
What is the Openwork Den?
The Den is Openwork's cloud-hosted control plane that manages organization-wide settings, model provider credentials, and marketplace content. According to the different-ai/openwork source code, it exposes a single MCP endpoint at https://api.openworklabs.com/mcp/agent that local servers communicate with via apps/server/src/cloud-plugins.ts when remote capabilities are required.
Do I need to write tests for every contribution?
Yes. The project requires end-to-end coverage using @openwork/testkit. You must add slow specs in evals/specs/ that exercise the complete flow of your changes. This practice ensures the CI remains green and verifies that your code satisfies hidden tests not visible in the local test runner.
What is the difference between pnpm dev and pnpm dev:worktree?
pnpm dev starts the UI and server in a shared development profile suitable for most changes, accessible at http://localhost:5173 with CDP debugging on port 9223. pnpm dev:worktree creates an isolated profile with separate state, which is essential when working on parallel features or long-running branches that might conflict with each other.
How do I debug the Electron client?
When running pnpm dev, the console prints a banner like [openwork] dev profile=… cdp=http://127.0.0.1:9223. Navigate to this URL in Chrome to attach DevTools and debug the Electron process directly, or use the headless script at scripts/dev-headless-web.ts for CI debugging.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →