mcp server
coworker
Local-first AI coding assistant desktop app — built with Electron, React, and LangGraphdevidollamachatgptreactchatgptollamadevtoolside
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, 2026Coworker Agent
Local-first AI coding assistant desktop app — chat with your code, powered by any LLM.
Features
| Feature | Feature | Feature | Feature |
|---|---|---|---|
| 🗨️ 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:
| Platform | Install |
|---|---|
| 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.appon 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 assistants | Coworker |
|---|---|
| Cloud-dependent, data leaks via API | True local-first — all data stays on your machine |
| Tied to one provider or vendor | Multi-provider agnostic — any OpenAI-compatible API, Ollama, custom |
| Basic chat with no memory beyond session | Long-term memory — auto-extract from interactions, persist across sessions |
| No control over agent actions | HITL by default — manually approve every command and file change |
| No audit trail | Full trace — export agent traces, tool audit logs, rollback to any state |
| Black-box tool execution | Transparent — every change logged with before/after diffs in a human-readable format |
| Limited tool capabilities | Rich 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 thememory_readtool. - Manual write — the agent uses the
memorytool to write durable facts to its ownBASE/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:- extracts durable facts and consolidates them into the agent's
MEMORY.md; - appends a short session note to
SESSIONS/<date>.md(once per day); - logs a line in
DREAMS.md(e.g.consolidated · new 3).
- extracts durable facts and consolidates them into the agent's
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 toARCHIVE/DREAMS-YYYY-MM.md.SESSIONS/<date>.md— day files older than the current month are merged intoARCHIVE/SESSIONS-YYYY-MM.mdand removed.
Archives live under <agent>/ARCHIVE/ — they are not injected into the prompt
and stay readable on demand via memory_read.
How to verify
- In a chat, state a durable fact, e.g. "I prefer replies in Chinese" or "this project's backend binds port 9527".
- Stop chatting for a few turns (or wait for the nudge interval).
- Check
memory/<project>/default_agent/BASE/:MEMORY.mdgains a new entry;DREAMS.mdshowsnew N · consolidated(notnew 0);SESSIONS/<today>.mdcontains a session note.
- For detail, restart with
COWORKER_LOG_LEVEL=DEBUGand watchapp.logfordream 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
activeand 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+Oshortcut.
Logging & Observability
All logs are written to the app data directory by default (macOS:
~/Library/Application Support/Coworker; override with COWORKER_DATA_DIR).
| File | Contents | Governance |
|---|---|---|
app.log + app.log.N | Main runtime log (JSON, one record per line) | Rotated by size (default 10 MB × 5) |
agent_trace.jsonl | Agent activity trace (events / state / context) | Rolling retention, default last 100 (adjustable in settings) |
tool_audit.jsonl | Tool-call audit | Rolling retention, default last 100 (adjustable in settings) |
command_approvals.json | Command approval records | Keeps last 100 + guaranteed 25 |
worker_events/<run>.jsonl | Sub-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.logautomatically carrysession_id(session-related requests and the whole/chat/stream//chat/interjectflow), so you cangrep '"session_id":"<id>"'to pull a single session's runtime log.
Technology Stack
| Layer | Technologies |
|---|---|
| Desktop | Electron 43 · contextBridge · tray · electron-updater |
| Frontend | React 19 · Vite 8 · Zustand · xterm.js · Tailwind · Shiki |
| Backend | Python 3 · FastAPI · Uvicorn · Pydantic · SQLite · LangGraph |
| Agent | LangChain 1.3 · LangGraph 1.2 · Multi-level review middlewares |
| Models | OpenAI-compatible APIs · Ollama · custom base URLs |
| MCP | MCP 1.29 · langchain-mcp-adapters 0.3 · Five transport protocols |
| Web Search | Multi-backend pluggable search — DuckDuckGo (default, keyless) · Tavily (optional paid) · built-in browser (Bing / Google / DDG / Baidu / Sogou) with automatic fallback |
| Extensibility | MCP servers · SKILL.md skills · SkillHub / ClawHub marketplaces |
| i18n | en · 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
- GitHub Releases · Installers for macOS, Windows, Linux
- GitHub Issues · Report bugs and request features
- CONTRIBUTING.md · How to contribute
License
MIT — see LICENSE.
Built by Coworker Contributors.