Common Issues When Using different-ai/openwork and How to Fix Them
The most common problems with OpenWork involve development profile lock contention on Windows, UI glitches in the in-app browser, stuck loading indicators, and monorepo dependency mismatches across its Electron-MCP-Den architecture.
OpenWork is a local-first, cloud-ready desktop app that unifies AI agents, skills, and MCPs behind a single control surface. Its three-layer architecture—Electron desktop runtime, remote MCP service, and cloud-hosted Den console—creates multiple failure points where platform-specific behaviors and configuration drift cause friction. Understanding how these layers interact, and where the open-source codebase handles state and events, is essential for troubleshooting effectively.
Development Profile Locking and Port Contention
The most frequently reported startup failure occurs when pnpm dev or pnpm dev:worktree aborts with a profile lock error or CDP port conflict. OpenWork uses profile-based isolation via the OPENWORK_DEV_PROFILE environment variable to separate credentials, ports, and runtime state between development contexts.
Root Cause: Stale Lock Files
Each profile creates a lock file to prevent multiple Electron instances from sharing state. When a process crashes or exits uncleanly, the lock persists and blocks subsequent launches. The lock location defaults to ~/.openwork/dev-profile-lock unless overridden.
Solution: Force a Fresh Profile
# Remove stale lock and start with isolated profile
rm -rf ~/.openwork/dev-profile-lock
OPENWORK_DEV_PROFILE=my-feature \
OPENWORK_ELECTRON_USE_MOCK_KEYCHAIN=1 \
pnpm dev
The OPENWORK_DEV_PROFILE=my-feature parameter forces allocation of a new CDP port and lock file. Setting OPENWORK_ELECTRON_USE_MOCK_KEYCHAIN=1 prevents macOS keychain authorization dialogs from blocking startup—particularly useful in CI or headless environments.
Platform-Specific Runtime Issues
Windows and macOS exhibit distinct failure modes due to how Electron handles STDIO, sandboxing, and native system integrations.
Windows: Dev Server Blocking and Task Abortion
Issue #3457 documents npm run dev blocking the agent process on Windows, causing tasks to abort when the terminal remains in the foreground. This stems from Windows command-line buffering interfering with Electron's STDIO pipe handling.
Workaround: Launch through a detached console or force new process group:
# Force new console window on Windows
cmd /c start pnpm dev
# Or use cross-env to isolate environment
npx cross-env OPENWORK_DEV_PROFILE=win-dev pnpm dev
Adding --max-old-space-size=4096 to Node flags also prevents long GC pauses that compound the blocking behavior.
In-App Browser: Right-Click and Passkey Hangs
Issue #3459 reports non-functional right-click menus and multi-minute passkey prompt hangs in the embedded Chromium browser. The root cause lies in contextIsolation settings and missing contextmenu event registration in the renderer preload.
Fix in preload script (apps/desktop/src/electron/preload.ts):
const { contextBridge, ipcRenderer } = require('electron');
// Expose safe API to renderer
contextBridge.exposeInMainWorld('openwork', {
showContextMenu: (x: number, y: number) =>
ipcRenderer.send('show-context-menu', { x, y })
});
Fix in renderer (apps/desktop/src/renderer/browser.ts):
window.addEventListener('contextmenu', (e) => {
e.preventDefault();
// Forward to main process for native menu
window.openwork.showContextMenu(e.clientX, e.clientY);
});
For passkey hangs, ensure navigator.credentials polyfills are loaded before WebAuthn requests, or disable passkey auto-prompt via OPENWORK_SKIP_PASSKEY=1.
Stuck Session Loading Indicator
Issue #3462 describes the loading spinner persisting after task completion. The bug resides in apps/desktop/src/renderer/loading.tsx where the runTask promise lacks guaranteed cleanup.
Correct pattern:
// loading.tsx
async function runTask(task: () => Promise<void>): Promise<void> {
setLoading(true);
try {
await task();
} catch (err) {
setError(err);
throw err;
} finally {
setLoading(false); // Guaranteed execution
}
}
The finally block ensures setLoading(false) runs regardless of success or failure, eliminating the stuck spinner state.
MCP and Remote Service Connectivity
OpenWork's Model-Control-Plane exposes search_capabilities and execute_capability tools via https://api.openworklabs.com/mcp/agent. Failures here typically manifest as "MCP tool not found" or timeout errors in Claude Code, Codex, or Cursor integrations.
Common Causes
- Stale API key in dev profile credentials
- CORS rejection from custom Den deployments
- Version mismatch between local client and remote MCP schema
Debugging Steps
# Verify MCP endpoint health
curl -H "Authorization: Bearer $OPENWORK_API_KEY" \
https://api.openworklabs.com/mcp/agent/health
# Test capability search locally
npx openwork-cli mcp search --query "file-ops"
The CLI source in packages/mcp/src/index.ts implements the client-side protocol; check MCPClient.searchCapabilities() and executeCapability() method signatures when building custom integrations.
Dependency and Build Tool Conflicts
OpenWork uses pnpm workspaces with Turborepo for build orchestration. Dependency bumps—especially in postcss, vite, or turbo—frequently break builds when lock files desynchronize across packages.
Symptoms
Module not founderrors after pulling mainturbocache corruption causing stale builds- Type conflicts between workspace package versions
Resolution Workflow
# From repository root
rm -rf node_modules **/node_modules pnpm-lock.yaml
pnpm install # Regenerate unified lock
pnpm run build # Verify full build
pnpm turbo run dev --filter=@openwork/desktop
Critical: Always run pnpm install at the monorepo root, never in individual package directories. The pnpm-workspace.yaml defines workspace boundaries; violating this causes phantom dependency resolution.
Per-Session Agent Selection Drift
A subtle configuration issue occurs when the per-session agent selector fails to persist across window reloads. This relates to how apps/desktop/src/electron/main.ts serializes session state to the profile's session.json.
Ensure your dev profile has write permissions:
# Check profile directory permissions
ls -la ~/.openwork/profiles/$OPENWORK_DEV_PROFILE/
# Reset session state if corrupted
rm ~/.openwork/profiles/$OPENWORK_DEV_PROFILE/session.json
Summary
- Profile locks: Delete
~/.openwork/dev-profile-lockand use uniqueOPENWORK_DEV_PROFILEvalues to isolate development contexts - Windows blocking: Launch via
cmd /cor detached process to prevent STDIO deadlock - Browser UI: Register
contextmenulisteners in renderer and preload; disable passkey auto-prompt if needed - Loading states: Always place
setLoading(false)infinallyblocks of async task runners - Dependencies: Run
pnpm installexclusively from repository root after any version bumps
Frequently Asked Questions
Why does OpenWork hang on startup with "profile locked" error?
The previous Electron instance did not shut down cleanly, leaving a stale lock file in ~/.openwork/dev-profile-lock. Remove this file or specify a new OPENWORK_DEV_PROFILE environment variable to force creation of a fresh lock and CDP port allocation.
How do I fix right-click menus in the embedded browser?
The in-app browser requires explicit contextmenu event handling. Register a listener in your renderer process that prevents the default chromium menu and communicates with the main process via contextBridge to display native menus. Ensure contextIsolation is properly configured in the preload script.
What causes the loading spinner to stay active after tasks complete?
The async task runner in loading.tsx lacks guaranteed cleanup. Move setLoading(false) into a finally block so it executes regardless of whether the task succeeds, fails, or throws—matching the pattern shown in the fixed implementation above.
How should I update dependencies in the OpenWork monorepo?
Always run pnpm install from the repository root, never in individual package directories. This ensures pnpm-lock.yaml stays synchronized across all workspaces defined in pnpm-workspace.yaml. After major bumps, clear node_modules and the lock file entirely before reinstalling.
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 →