by linmy666
MadCop — local-first AI agent desktop workstation (v0.9). Multi-model chat, tool-use, MCP servers, 12 workflow modes, knowledge base, AI design tool, persistent workspace.
# Add to your Claude Code skills
git clone https://github.com/linmy666/madcopmadcop is an open-source ai agents skill for AI coding assistants such as Claude Code, Codex CLI, and ChatGPT, built by linmy666. MadCop — local-first AI agent desktop workstation (v0.9). Multi-model chat, tool-use, MCP servers, 12 workflow modes, knowledge base, AI design tool, persistent workspace. It has 62 GitHub stars.
madcop's catalog security scan is still queued. You can run an instant dependency and prompt-injection check now with the "Scan for vulnerabilities" button above.
Clone the repository with "git clone https://github.com/linmy666/madcop" and add it to your Claude Code skills directory (see the Installation section above).
madcop is primarily written in TypeScript. It is open-source under linmy666 on GitHub, so you can review or fork the full source.
Yes. SkillsLLM lists many other AI Agents skills you can browse and compare side by side. Open the AI Agents category from the badge at the top of this page, or use the Related Skills and comparison links further down to weigh madcop against similar tools.
No comments yet. Be the first to share your thoughts!
Unlocks once the catalog security scan passes (runs nightly).
The deep catalog scan for this skill is still queued. Run an instant dependency check now instead.
A local-first AI agent desktop workstation.
MadCop is a cross-platform desktop application that brings the power of modern LLMs into a private, agentic workflow. It runs as a single Electron binary on macOS, Windows, and Linux, talks to any OpenAI-compatible API endpoint, and keeps your conversations, files, and knowledge base entirely on your machine. No cloud lock-in, no per-seat fees, no data leaving the device.
This document explains the why behind the major design decisions — written for product managers and reviewers who want to understand how the system is put together, not just a list of features.
The dominant LLM desktop clients (ChatGPT, Claude.ai, Gemini) are excellent chat surfaces but they assume a specific shape of interaction: one human, one model, one conversation at a time, with vendor-managed tools and memory. That works for "answer this question" but it does not work for "I need to (a) search the web, (b) read a local file, (c) summarise the result, (d) save a Markdown report to disk" — which is a normal afternoon for a product manager, analyst, or engineer.
MadCop is built around three observations:
git history, screenshots, contracts — the substance of real work sits on the user's disk. A client that can only attach a single file per message (or pays per-token for cloud RAG) punishes the people who already have the answer.So the design goal is: a thin local shell that lets the user pick their own model, hand it their own files, and let the system orchestrate the rest. Everything else is in service of that.
┌─────────────────────────────────────────────────────────┐
│ Electron Shell │
│ ┌────────────────────┐ ┌────────────────────────┐ │
│ │ Vue 3 + Pinia + │ │ Python Backend │ │
│ │ Tailwind v4 UI │ │ (FastAPI + Uvicorn) │ │
│ │ (Renderer Process)│←→│ │ │
│ └────────────────────┘ │ ┌──────────────────┐ │ │
│ │ │ LLM Client │ │ │
│ ┌────────────────────┐ │ │ (OpenAI Compat) │ │ │
│ │ Workspace Picker │ │ └──────────────────┘ │ │
│ │ Sidebar / Tabs │ │ ┌──────────────────┐ │ │
│ │ Chat / Composer │ │ │ Tool Registry │ │ │
│ └────────────────────┘ │ │ + MCP Bridge │ │ │
│ │ └──────────────────┘ │ │
│ │ ┌──────────────────┐ │ │
│ │ │ Workflow Engine │ │ │
│ │ │ + 12 Modes │ │ │
│ │ └──────────────────┘ │ │
│ │ ┌──────────────────┐ │ │
│ │ │ Memory Pipeline │ │ │
│ │ │ (5-tier) │ │ │
│ │ └──────────────────┘ │ │
│ └────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
The architecture is intentionally two processes talking over HTTP — not one big monolith — for three reasons:
madcop.server module runs without Electron (over plain HTTP/WebSocket) for CI, scripting, or embedding in other tools.Routing is the single most important design question in any LLM client. MadCop routes on three axes simultaneously:
The user configures one or more model providers in the Settings panel. Each provider is a name + base URL + API key + model id (any OpenAI-compatible endpoint). The frontend exposes the active provider as a useSettingsStore.currentModel ref; the backend receives a model field on every POST /api/chat and forwards it to the OpenAI-compatible client.
This means there is no "default model" hard-coded in the backend. If you don't configure one, you get a clear error on the first request. The model lives in user data, not in the product.
Different models from different vendors have wildly different tool-use quality. The backend's tool dispatcher handles this by tuning the system prompt per model family. The backend's tool dispatcher (madcop/tools/registry.py) registers the same toolset regardless of model, but the system prompt is tuned to nudge the model toward emitting function calls. Specifically, every chat request includes an explicit instruction:
"When the user asks you to do anything that requires real-time information, you MUST call the
web_searchtool. Do not make up answers. Call the tool directly — do not output the tool's parameter description."
This works around the most common failure mode of self-hosted Chinese-tuned models (outputting the JSON schema as text instead of as a structured tool_calls array).
A single chat turn can be either "answer this" (one LLM call) or "search the web, write a report, save to disk" (many LLM calls with tool side effects). The Mode Selector in the composer exposes 12 preset modes from Google's "Agent design patterns" catalog:
single_agent — one LLM + tools, the defaultsequential — Agent A → B → C, each consuming the previous outputparallel — same input fanned out to N workers, results mergedcoordinator — a router agent classifies input, dispatches to a specialisthierarchical — top-level plan, sub-tasks, recurseswarm — many agents with shared blackboardloop — produce, critique, revise until a quality threshold is metreview_critique — producer + revieweriterative_refine — feedback loop with a separate evaluatorhuman_in_loop — explicit user checkpointreact — Reason + Actcustom — user-defined graphWhen a mode is selected, the chat endpoint hands the request to the workflow engine (madcop/workflow/executor.py), which walks the mode's graph of nodes. Each node is a Python class with an execute(ctx) method that receives the inputs from upstream nodes and yields a result. The engine emits SSE events at each step so the UI can show progress live.
For users who don't want to pick a mode, the frontend performs a lightweight keyword-based intent classifier (_classifyAndPlan in chatStore.ts) that detects multi-step requests (contains words like 调研 / 搜索 / 保存 / 生成 / 写到) and injects an inline task plan into the system prompt:
"First, search using web_search. Second, generate the report and save it to ~/Downloads/madcop/ as report.md using write_file. Third, reply to the user when done."
This gives the user the experience of the multi-agent system without the cognitive overhead of picking a mode from a dropdown.
The tool system is the surface where "agent" stops being marketing and becomes real. MadCop's design is a single registry that everything reads from, with three extension points:
Built-in tools — registered in madcop/tools/__init__.py::default_registry(). These include:
web_search (DuckDuckGo, no API key needed)web_fetch (httpx + BeautifulSoup-style HTML→text)read_file / write_file / edit_file (path-confined to allowlisted dirs)weather (wttr.in, no key)clarify (returns a structured question back to the user)MCP servers — any external Model Context Protocol server can be registered at startup via madcop/tools/mcp.py. The bridge translates MCP tools/call into internal Tool.__call__ invocations. This means a user can add a private internal API or a database client without forking MadCop.
User-defined Python tools — any function decorated with @tool("name", description="...") is auto-registered. The decorator captures the signature and produces an OpenAI-compatible JSON schema. This is the path for one-off internal tools.
The dispatcher is stateless: each tool call is registry.dispatch(tool_call) -> ToolResult. The function looks up the tool by name, validates the arguments against the schema, calls the function, and wraps the return value in a ToolResult(is_error=..., content=...). The chat loop serializes the result and appends it to the message history before the