Skip to content
Conduit

mcp server

coworker

Local-first AI coding assistant desktop app — built with Electron, React, and LangGraphdevidollamachatgptreactchatgptollamadevtoolside

leonjackman/coworkercommunitylistedunreviewed

Set up

Runs on your computer. Pick your agent and operating system.

This project does not publish an install method we can turn into a config. Follow the README instead.

README

synced Oct 25, 2026

Coworker Agent

Local-first AI coding assistant desktop app — chat with your code, powered by any LLM.

License: MIT CI GitHub release macOS Windows Linux

English · 简体中文


Features

FeatureFeatureFeatureFeature
🗨️ Streaming Chat💬 Built-in Chat Project📥 Message Queue & Interject🔌 Multi-Provider
🧠 Long-Term Memory👥 Multi-Agent Teams ⚠️👤 Sub-Agents🎯 Goal Mode
⚙️ Workflow Studio (Beta)🔄 MCP Integration📦 Skills🌐 Web Search & Fetch
🖥️ Built-in Browser🧭 Desktop Control (macOS; Win Beta)🔒 Human-in-the-Loop📓 Change Tracking
🖥️ Integrated Terminal🔎 Audit & Traces✏️ Message Editing📄 Office & PDF Documents
🍎 macOS App Scripting📎 File Attachments🔗 Session Cross-Reference🛡️ Sensitive File Protection
📋 Plan / Build Modes🌎 i18n (11 languages)🎨 Themes🔊 Sound Notifications
📊 Context Budget🔄 Auto-Update📊 Project Dashboard

📖 Full feature guide → FEATURES.md

⚠️ Multi-Agent (Experimental) — Multi-agent teams, departments, and delegation are an experimental capability still under active development: the feature set is not yet complete, behavior may change, and the project mode is immutable after creation. Prefer single-agent mode for daily work.

🧪 Platform status (a quick heads-up) — macOS is the one we polish the most, so treat it as the stable baseline. On Windows, Computer Use and Workflow are still in BETA — they're usable, but a bit rough around the edges: while it works, your real mouse pointer moves, and the occasional Store app or window switch can trip it up. Linux hasn't really been tested yet — expect missing pieces and the odd obvious bug.


Screenshots

Main View

Workflow Studio


About Coworker

Coworker is a new product actively under rapid development. New features are shipped frequently and breaking changes may happen. Some features are still in progress or may contain bugs. We encourage you to try it out, explore, report issues, and give feedback — your input directly shapes the direction of this project.

New releases are published irregularly as the team moves quickly. Star the repo or watch releases to stay up to date.


Product Positioning

Coworker is a local-first, fully-featured AI coding assistant. Unlike traditional cloud-based coding tools, Coworker's core value proposition is:

  • Privacy first — all data (code, memory, chat logs) stays on your machine; nothing touches a third-party server
  • Model agnostic — no vendor lock-in; use OpenAI-compatible APIs, Ollama, or any custom endpoint
  • Full-powered Agent — web search, browser automation, file management, sub-agents, MCP extensions, and a skill marketplace
  • Human-in-the-loop — built-in review mechanism so you approve every critical action
  • Fully traceable — complete audit trails, agent trace export, rollback to any state
  • Extensible — MCP protocol + SKILL.md skill system + marketplace ecosystem

Install

Pre-release — Coworker is under active development. Features are added and improved regularly. Download to try it out, report bugs, and help shape the road ahead.

Install from Releases (Recommended)

Pre-built desktop installers are available from GitHub Releases:

PlatformInstall
macOS (Apple Silicon)Download .dmg
Windows 10+Download .exe
Linux (x64)Download .AppImage

macOS builds are unsigned / un-notarized. May require xattr -d com.apple.quarantine /Applications/Coworker.app on first launch.

Install from Source

Clone the repository and run the development environment (see below).


Quick Start

Desktop App (from source)

macOS / Linux:

./coworker_desktop.command     # macOS
./coworker_desktop.sh          # Linux

Windows (pick one):

coworker_desktop.bat           # double-click, or run from cmd (bypasses the PS execution policy)
.\coworker_desktop.ps1         # run from a PowerShell session that allows local scripts

Each launcher prepares the Python venv and Node dependencies, rebuilds the frontend only when its inputs changed, starts the backend (FastAPI), and launches the Electron app once the backend is healthy.

Useful flags:

COWORKER_SKIP_DESKTOP=1 ./coworker_desktop.command   # backend only (smoke test)
COWORKER_FORCE_BUILD=1  ./coworker_desktop.command   # force a frontend rebuild

On Windows set the same values as environment variables, e.g. $env:COWORKER_SKIP_DESKTOP="1"; .\coworker_desktop.ps1.

For all platforms, download the pre-built installer from GitHub Releases.

Configure an LLM Provider

Open Settings → Providers in the app UI:

  • Pick from 32 built-in provider presets (OpenAI, Anthropic, Google Gemini, DeepSeek, Qwen, Moonshot, Zhipu, and more), or add a custom OpenAI-compatible endpoint
  • Set the base URL, model name, and API key for the chosen provider
  • Keys are stored in the macOS Keychain (or a 0600-protected file)
  • Use the built-in "Test" button to verify connectivity

For local models via Ollama:

Base URL: http://localhost:11434/v1
Model: your_model_name

Development

Backend

cd backend
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
uvicorn main:app --host 127.0.0.1 --port 9527

Frontend

cd frontend
npm install
npm run dev

Full Dev Mode

# Terminal 1 — FastAPI backend
cd backend && source venv/bin/activate && uvicorn main:app --host 127.0.0.1 --port 9527

# Terminal 2 — Vite dev server
cd frontend && npm run dev

# Terminal 3 — Electron (points to Vite dev server)
NODE_ENV=development npx electron . --no-sandbox

Code Layout

backend/main.py                 # thin entry: composition root + re-exports + router wiring
backend/coworker/api/*.py       # domain routers & helpers (state, streaming, chat, sessions,
                                #   memory_org, settings, workspace, ops, approvals, providers,
                                #   terminal, skills, browser, workflows) — singletons live once in state.py
backend/coworker/**             # domain logic (agent / memory / providers / skills / search / workflows / documents …)
frontend/src/App.tsx             # app shell (state + wiring) importing domain components
frontend/src/App.css             # @import hub → frontend/src/styles/*.css (per-domain styles)
frontend/src/components/**       # React feature components (sidebar / panels / modals …)
frontend/src/lib/**              # shared front-end logic (messageParts / i18n / theme …)
frontend/src/locales/*.json      # 11-language dictionaries (bundled statically at build)
electron/main.js                 # desktop shell: window, backend boot, browser bridge

Startup: the window opens immediately and the UI is already fully localized; the bundled backend boots in parallel and is waited on for up to 1 minute before reporting an error.


Chat Project (Built-in Casual Chat)

Coworker ships with a system-reserved Chat project pinned to the top of the sidebar, so you can start a casual conversation right away — no need to create a project first.

  • Zero-setup chat — on first launch the onboarding screen offers "Start chatting"; the global new-chat action falls back to the Chat project when you have no real projects yet.
  • Always there & safe — it is created automatically at startup and self-heals if its folder is deleted; it cannot be deleted or renamed. Its workspace is a system-designated sandbox folder (COWORKER_DATA_DIR/chat), fully isolated from your real projects.
  • Lazzzy Boy persona — the agent in the Chat project adopts the relaxed "lazy boy" personality of the Lazzzy Boy studio: casual, concise, and smart. Unless you explicitly ask, it won't read or edit files, run commands, or call search / MCP tools — it just talks. (Tools remain available, so it can still work inside the sandbox on request.)
  • Localized name — the project name follows your UI language (Chat / 聊天 / チャット …).

What Makes Coworker Different

Traditional coding assistantsCoworker
Cloud-dependent, data leaks via APITrue local-first — all data stays on your machine
Tied to one provider or vendorMulti-provider agnostic — any OpenAI-compatible API, Ollama, custom
Basic chat with no memory beyond sessionLong-term memory — auto-extract from interactions, persist across sessions
No control over agent actionsHITL by default — manually approve every command and file change
No audit trailFull trace — export agent traces, tool audit logs, rollback to any state
Black-box tool executionTransparent — every change logged with before/after diffs in a human-readable format
Limited tool capabilitiesRich tool ecosystem — web search, built-in browser, sub-agents, MCP extensions, SKILL.md skill marketplace

Long-Term Memory

Coworker keeps a per-agent, per-project Markdown memory library at ~/Library/Application Support/Coworker/memory/ (macOS; the data dir follows COWORKER_DATA_DIR). All files are plain, human-editable Markdown.

memory/
├── MEMORY.md · USER.md · AGENT.md      # system-level facts (user-maintained)
└── <project>/                          # one timestamp-named dir per project
    ├── BASE/                           # user-maintained project facts
    └── <agent>/
        ├── BASE/                       # SOUL · AGENT · MEMORY.md (agent facts)
        │   └── DREAMS.md               # auto-extraction review diary
        └── SESSIONS/<date>.md          # per-day session notes (auto + manual)

How it works

  • Injection (read) — each turn the relevant memory files are injected into the system prompt (bounded by memory.char_limit, default 2000 chars). Extra files and session notes are read on demand with the memory_read tool.
  • Manual write — the agent uses the memory tool to write durable facts to its own BASE/MEMORY.md (or a topic file / SESSIONS/<date>.md), deduplicated and approval-gated under the default permission.
  • Auto-extract (dream) — every N turns (controlled by COWORKER_MEMORY_NUDGE_INTERVAL, default 10), a background pass reviews the recent transcript with an LLM and:
    1. extracts durable facts and consolidates them into the agent's MEMORY.md;
    2. appends a short session note to SESSIONS/<date>.md (once per day);
    3. logs a line in DREAMS.md (e.g. consolidated · new 3).

Auto-extract uses the provider configured under memory settings (memory_extract_model; falls back to the default provider). It is controlled by COWORKER_MEMORY_ENABLED and COWORKER_MEMORY_AUTO_EXTRACT (both default on).

How it stays bounded

Memory files are governed lazily (at write time, no background job):

  • MEMORY.md / USER.md — consolidation keeps the file under the injection budget (default 4000 chars); the append-only fallback is FIFO-capped at the same budget (oldest entries are dropped first, the newest fact is never lost).
  • DREAMS.md — only the current month's entries stay in the live file; older months are moved to ARCHIVE/DREAMS-YYYY-MM.md.
  • SESSIONS/<date>.md — day files older than the current month are merged into ARCHIVE/SESSIONS-YYYY-MM.md and removed.

Archives live under <agent>/ARCHIVE/ — they are not injected into the prompt and stay readable on demand via memory_read.

How to verify

  1. In a chat, state a durable fact, e.g. "I prefer replies in Chinese" or "this project's backend binds port 9527".
  2. Stop chatting for a few turns (or wait for the nudge interval).
  3. Check memory/<project>/default_agent/BASE/:
    • MEMORY.md gains a new entry;
    • DREAMS.md shows new N · consolidated (not new 0);
    • SESSIONS/<today>.md contains a session note.
  4. For detail, restart with COWORKER_LOG_LEVEL=DEBUG and watch app.log for dream done ... added=N transcript=… chars.

Run the memory self-checks with:

cd backend && ./venv/bin/python coworker/memory/selftest.py

Message Queue (Queue While Streaming)

While the agent is replying you don't have to wait — keep typing and send your next message right away.

  • Composer stays editable during streaming — the input box is never locked while a reply is in progress; only the "connecting" phase disables it.
  • Sending queues the message — pressing Enter / the send button while a stream is running does not start a parallel turn. The message is appended to a per-session FIFO queue and auto-sends as the next request once the current stream finishes (done / error / stopped). Send without content shows the Stop button instead, so you can still interrupt the running task.
  • Queued messages are visible — each pending message is listed in the task-list card above the composer (one row per message) with an Interject now (↳) action and a ✕ remove action, so nothing is hidden behind an icon.
  • Edits & regenerations stay serialized — only one stream runs per session; queued messages never race the stream they are waiting for.

How interrupted turns restart cleanly

If a stream is aborted (Stop, client disconnect), the backend marks the session as interrupted. The next /chat/stream forgets the dirty runtime checkpoint and rebuilds from the session history, so the new (or first queued) message becomes the active instruction instead of the model continuing the original task from a stale mid-task checkpoint.

Interject (guide a running task)

While the agent is streaming, pick any queued message and hit Interject now (↳) to steer the reply without stopping or restarting it.

  • Guides within the current run — interjecting does not abort the in-flight stream. The message is handed to the running agent and folded into its next model call, so the LLM's subsequent output and tool steps follow your steer.
  • Shown as a "Steered" card — the interjected text appears as a notice inside the assistant bubble (not as a separate user bubble), keeping the transcript clean.
  • Never lost on a late steer — if the task already finished before the steer could be consumed, the interjection is automatically continued as the next turn instead of being dropped.

Queued messages auto-send one-by-one once the stream settles; use Interject now when you want guidance to take effect within the current run instead of waiting for it to finish.


Goal Mode

Set a persistent objective with /goal <objective> and the agent keeps working across multiple rounds without further input until it marks the goal complete or blocked. A progress card (objective, status, elapsed time, token-budget bar) is pinned in the task panel.

  • Input-box Stop stops the current task; the goal stays active and needs a kick (new message / resume / reopen) to continue.
  • TodoBlock pause / resume / clear control the goal itself — pausing lets the current round finish, then stops further rounds without aborting the run.
  • Goals are strictly per-session and never affect other sessions.
  • If a human-in-the-loop approval or question is raised mid-run, the loop pauses and resumes after you approve.

Project Dashboard

Every project has a read-only dashboard that makes its files, agents, git status and session history visible at a glance.

  • Five tabs — Overview (project info, git status, and stats) · Files · Agents · Memory · Session history.
  • File explorer — a keyboard-navigable file tree (ARIA accessible) with rich previews: syntax-highlighted code with line numbers, virtual-scrolled CSV / XLSX tables, and a draggable split pane.
  • Open externally — any file can be opened in your system's default app right from the dashboard.
  • Quick access — open it from the sidebar or with the Cmd+O shortcut.

Logging & Observability

All logs are written to the app data directory by default (macOS: ~/Library/Application Support/Coworker; override with COWORKER_DATA_DIR).

FileContentsGovernance
app.log + app.log.NMain runtime log (JSON, one record per line)Rotated by size (default 10 MB × 5)
agent_trace.jsonlAgent activity trace (events / state / context)Rolling retention, default last 100 (adjustable in settings)
tool_audit.jsonlTool-call auditRolling retention, default last 100 (adjustable in settings)
command_approvals.jsonCommand approval recordsKeeps last 100 + guaranteed 25
worker_events/<run>.jsonlSub-agent run stream events (replayable)Last 200 runs / total ≤ 100 MB

Controls:

  • Env vars: COWORKER_LOG_LEVEL, COWORKER_LOG_MAX_BYTES, COWORKER_LOG_BACKUP_COUNT, COWORKER_JSON_LOG, COWORKER_HTTP_LOG (request log toggle), COWORKER_WORKER_EVENTS_MAX_RUNS / COWORKER_WORKER_EVENTS_MAX_BYTES.
  • Runtime API: POST /settings/log-level (switch level, persists), POST /settings/log-config (level / rotation / JSON / request log, applies immediately and persists), POST /settings/truncate-log (clear or keep last N bytes), GET /settings/log-file (paginated read).
  • Request log: every HTTP request is recorded via coworker.http (method / path / status / latency / request_id); health-check and log-read endpoints are skipped; token / key query params are redacted.
  • Session correlation: JSON records in app.log automatically carry session_id (session-related requests and the whole /chat/stream / /chat/interject flow), so you can grep '"session_id":"<id>"' to pull a single session's runtime log.

Technology Stack

LayerTechnologies
DesktopElectron 43 · contextBridge · tray · electron-updater
FrontendReact 19 · Vite 8 · Zustand · xterm.js · Tailwind · Shiki
BackendPython 3 · FastAPI · Uvicorn · Pydantic · SQLite · LangGraph
AgentLangChain 1.3 · LangGraph 1.2 · Multi-level review middlewares
ModelsOpenAI-compatible APIs · Ollama · custom base URLs
MCPMCP 1.29 · langchain-mcp-adapters 0.3 · Five transport protocols
Web SearchMulti-backend pluggable search — DuckDuckGo (default, keyless) · Tavily (optional paid) · built-in browser (Bing / Google / DDG / Baidu / Sogou) with automatic fallback
ExtensibilityMCP servers · SKILL.md skills · SkillHub / ClawHub marketplaces
i18nen · zh · zh-TW · zh-HK · ja · ko · fr · de · es · pt-BR · ru

Contributing

Bug reports & feedback — Coworker is an evolving project. If something doesn't work, please open an issue with steps to reproduce. We'll fix it.

Contributions are welcome! Please read CONTRIBUTING · 贡献指南.


Links


License

MIT — see LICENSE.

Built by Coworker Contributors.

↑↓ navigate openesc close