Run a full general-purpose agent from one static Go binary.
ReAct, filesystem and shell tools, MCP, skills, OpenAI-compatible API with an embedded web UI, Telegram gateway, cron scheduler, long-term memory, and context compaction.
| Desktop (1920×1080) | Mobile (390×844) |
|---|---|
![]() |
![]() |
More screenshots
| Chat | Mobile chat |
|---|---|
![]() |
![]() |
| History | Scheduler |
![]() |
![]() |
| Scheduler — job editor | Settings |
![]() |
![]() |
| Settings — Skills | Settings — Appearance |
![]() |
![]() |
| Settings - MCP servers (project trust gate) | Background tasks |
![]() |
![]() |
Screenshots: desktop at 1920×1080, mobile at 390×844 from the embedded UI (coddy serve). Spec and dev workflow: docs/ui.md, layout tokens: DESIGN.md.
Console TUI (-tags cli) - bare coddy in a terminal, here in Konsole:
More console states and the capture sets: docs/cli.md.
Coddy is a distroless-friendly harness: drop it into minimal images (scratch, distroless, read-only workspaces) without a full OS shell. The same agent core is reachable from a terminal through the console TUI, an IDE over ACP, a browser or any OpenAI client over HTTP, Telegram through the messenger gateway, and cron through the scheduler. The grep and glob filesystem tools use system ripgrep when available and fall back to built-in Go implementations when it is not. The harness layer (ACP RPC, sessions, prompts, providers) stays the same if you tighten the toolset or drive it from automation instead of an IDE. The design also targets container fleets - many Coddy instances in Docker (orchestrator-defined limits, read-only rootfs, mounted workspace) with full control of each container, similar in spirit to agent OS / swarm-style agents, not a single shared chat pool.
- Features
- Quick start
- How to update
- Operating modes
- Editor and IDE integration
- Rules
- Skills
- MCP server integration
- Messenger gateway
- Configuration (reference)
- Architecture
- Documentation
- Examples (ACP over stdio)
- Persistent sessions
- Development
- License
- Harness-first - ACP server, session lifecycle, prompts, LLM backends, MCP merge, distroless-ready binary
- One process, every surface -
coddy serveruns whateverconfig.yamlenables: the REST gateway and embedded web UI (httpserver.enable), the Telegram bot (gateways.telegram.enable), the swarm relay (swarm.enable), the cron scheduler (scheduler.enable). They share one session manager, so a conversation started in a chat is live in the browser and can be continued in either.coddy serve --daemonputs it in the background under a dispatcher that starts it again when it dies, watchesconfig.yamlso a login or an edit made elsewhere reaches every surface, and replaces the process when a change moves a listen address;coddy serve status | stop | restartdrive it. Barecoddyis the interactive console (-tags cli) andcoddy acpserves editors; all of them share$CODDY_HOMEsessions - see Daemon, Console, HTTP API, Gateway - Remote control - point the console or ACP at a running server with
--remote <name|host:port|url>(plus--remote-token/CODDY_REMOTE_TOKEN), and switch the web UI between local and remote from the composer environment chip - see Remote control - Self-configuration - the agent edits its own YAML through staged uci-like commands (
config_get/config_set/config_changes/config_commit/config_revert/config_rollback): nothing touches the file until a commit you approve, which then validates, snapshots, and hot-reloads skills, rules, tools, and MCP servers - see Configuration reference - ReAct loop - LLM alternates between reasoning, acting (tool calls), and observing results (coding-agent persona out of the box)
- Three operating modes -
agent(full tool access),plan(planning + text files only), andask(read-only research: the model can only read the repository and search the web) - Rules - auto-discovers
.coddy/rules/, the shared.agents/rules/,.cursor/rules/,.claude/rules/,.codex/rules/, and nested**/AGENTS.md(agents.md) under the session cwd; the extension picks the dialect (.mdcCursor,.mdClaude Code) - see Rules - Skills - slash commands and
SKILL.mdpacks fromskills.dirs(defaults:~/.agents/skills,~/.coddy/skills,${CWD}/.coddy/skills; later dirs override earlier) - see Skills - Background tasks -
run_commandcan run detached (background: trueplus the model's ownexpected_secondsestimate);background_list/background_output/background_wait/background_stopcollect the result later, a Tasks drawer in the UI shows what is still running with a status ticker, and the permission dialog can widen a grant to a whole program (curl,git status) so a batch of similar calls asks once - see Background tasks - Subagents - the model delegates a bounded, self-contained task to a child agent with its own context window and session (
spawn_agent, foreground or detached); definitions are markdown files with YAML frontmatter under~/.coddy/agentsand.coddy/agents(Claude Code's.claude/agentsload too), two built-ins (general,explore) ship embedded, project files need a one-time approval (coddy agents trust <name>), tools and permission mode can only narrow, and every run is a background task with a read-only child transcript reachable from the Tasks drawer - see Subagents - Hooks - your own commands at lifecycle points of a session: a
PreToolUsehook can deny a tool call whatever the permission mode, approve it past the prompt, rewrite its arguments or add context, aPostToolUsehook can run a formatter or an audit log,UserPromptSubmitcan reject a prompt,Stopcan keep the agent working until a checklist is done,SessionStartadds context to every prompt,PreCompactcan veto a compaction,SubagentStartcan refuse a delegation andNotificationcan ping you when a permission prompt is waiting; definitions use Claude Code'shooks.jsonshape (~/.coddy/hooks.json,.coddy/hooks.json, and the workspace's.claude/settings*.jsonload too), project files need a one-time approval like MCP servers and subagents - see Hooks - MCP server integration - connect any MCP server for additional tools
- Multi-provider LLM - OpenAI, Anthropic, Ollama, any OpenAI-compatible API
- Context compaction - built-in
/compact [instructions]command and automatic summarization when the context reachescompaction.threshold_percent(default 80%) of the model'smax_context_tokens; the lastcompaction.keep_recent_turns(default 2) user turns stay verbatim and the full transcript is preserved on disk - see Configuration - Session export - built-in
/export [md|html|json|jsonl] [path]writes the conversation to a file in the workspace (markdown, a self-contained HTML page, JSON, or JSON Lines),coddy sessions export <id>does the same for a stored session from the shell;--no-toolsand--no-thinkingtrim it to the chat text - see Session export - Multimodal / file attachments - attach images and files via the composer (📎) when
multimodal: truein the model config; assets saved to~/.coddy/sessions/<id>/assets/and injected into the agent context; file chips displayed in the user bubble - Reasoning level - for reasoning models (gpt-5, o-series, Claude thinking models) a composer dropdown picks the effort level (
minimal/low/medium/high), mapped to OpenAIreasoning_effortor Anthropic extended-thinkingbudget_tokens; levels auto-detect from the model id and are configurable per model — see Configuration - ACP protocol - Coddy is an ACP server (
coddy acp); pair it with editors or scripts that implement an ACP client (see Editor and IDE integration) - SSH remote execution - built-in
ssh_run_commandtool runs commands on remote hosts over pure-Go SSH (no external binary); authenticates via SSH agent (SSH_AUTH_SOCK) or~/.sshkey files — see Configuration - Messenger gateway - optional Telegram bot adapter (
-tags gateway.telegram); per-user sessions, group isolation modes, admin ACL; extensible to Discord, Slack, etc. — see Messenger Gateway
Coddy is an ACP server (coddy acp). Obsidian, VS Code, Zed, scripts, and the bundled coddy serve UI are clients that share the same CODDY_HOME sessions when configured with the same home directory.
Configure clients with the absolute path to the binary rather than relying on PATH — some harnesses spawn the agent via cmd /c or sh -c without the user PATH (on Windows: %LOCALAPPDATA%\Programs\coddy\coddy.exe; see docs/install.md).
Zed — add one entry to settings.json, then pick Coddy under External Agents in the agent panel's new-thread menu:
"agent_servers": {
"Coddy": {
"type": "custom",
"command": "/home/you/.local/bin/coddy",
"args": ["acp"]
}
}Coddy's own modes (agent / plan / ask), its configured models, and its permission policy appear in Zed's composer, and its skills show up as slash commands.
Protocol details: docs/acp-protocol.md. Harness examples: examples/acp/.
Linux / macOS - release binary plus ~/.coddy bootstrap:
curl -fsSL https://coddy.dev/install.sh | bashWindows (PowerShell)
irm https://coddy.dev/install.ps1 | iexCreates ~/.coddy/config.yaml from the release config.example.yaml when missing. Puts coddy on PATH (Unix: ~/.local/bin; Windows: %LOCALAPPDATA%\Programs\coddy). On Linux and macOS it also installs the man page and the bash and zsh completions, and wires them into your login shell's rc file (--no-shell-setup opts out). Full installer options: docs/install.md.
Windows. The binary lands at
%LOCALAPPDATA%\Programs\coddy\coddy.exe; config and sessions live under%USERPROFILE%\.coddy\(use$env:USERPROFILE, not$HOME). Runtime commands selectpwsh, then Windows PowerShell, thencmd.exe; Unix builds selectbash, thensh. The installing terminal does not see the updatedPATH— open a new one or refresh it in place. Details:docs/install.md.
Linux packages - every release also publishes a .deb and an .rpm (x86_64 and arm64), carrying the binary, the man page and the shell completions:
curl -fsSLO https://github.com/coddy-project/coddy-agent/releases/latest/download/coddy_1.0.10_linux_amd64.deb
sudo apt-get install ./coddy_1.0.10_linux_amd64.deb # dnf install ./coddy_1.0.10_linux_amd64.rpmmacOS - the same release publishes a Homebrew cask:
brew install --cask https://github.com/coddy-project/coddy-agent/releases/latest/download/coddy.rbbrew install coddy by name needs Coddy in one of Homebrew's own repositories, which is
open work: as open-source command-line software it belongs in homebrew/core
as a formula, and Homebrew holds a self-submission to a higher notability bar than this repository
clears today.
Prefer a package on a machine you administer: the files are tracked by the package manager, and coddy update defers to it instead of overwriting a tracked binary. Details: docs/install.md.
Then set a provider key in ~/.coddy/config.yaml (or OPENAI_API_KEY in the environment) and run coddy serve for the UI, or coddy acp for an editor client.
Docker - same full binary in ghcr.io/coddy-project/coddy-agent: docker compose up -d (see Docker).
Upgrade later with coddy update -y (How to update).
Other installation methods (build from source, Go install, manual)
Prerequisites for building
- Go - same minor version as
go.mod(currently 1.25). - Git - used by the Makefile for the embedded version string.
- Node.js / npm - only if you build with
httpandui(the Makefile runsui-buildfor embedded assets).
Install with Go (lean module default, no http / UI tags)
go install github.com/EvilFreelancer/coddy-agent/cmd/coddy@latestFor coddy serve, the bundled SPA, scheduler, and memory, use a release binary (install script above) or build from source below.
Recommended full binary from source
git clone https://github.com/EvilFreelancer/coddy-agent
cd coddy-agent
make build TAGS="http ui scheduler memory cli gateway swarm"
make install # copies build/coddy to ~/.local/bin or /usr/local/binOr download archives from GitHub Releases.
Manual go build
When TAGS includes http and ui, run make ui-build first.
make ui-build
VERSION="$(make -s print-version)"
go build -tags=http,ui,scheduler,memory,cli \
-ldflags "-X github.com/EvilFreelancer/coddy-agent/internal/version.Version=${VERSION}" \
-o build/coddy \
./cmd/coddy/Lean ACP-only binary: make build (no http / UI / scheduler / memory tags).
Build reference: docs/build.md.
coddy -v prints the embedded version. coddy acp --help lists ACP flags (--home, --cwd, --config, etc.).
Use Makefile variable TAGS with spaces (make build TAGS="http ui scheduler memory cli gateway swarm"). go build uses commas (-tags=http,ui,scheduler,memory,cli,gateway,swarm).
| Tag | Enables | Docs |
|---|---|---|
memory |
Long-term memory copilot (memory.enable in YAML); with http, session memory REST under /coddy/sessions/{id}/memory/* |
external/memory/README.md |
http |
The REST gateway coddy serve runs under httpserver.enable, /docs, /openapi.yaml |
docs/http-api.md |
ui |
Embedded SPA on / (needs http) |
docs/ui.md, DESIGN.md |
scheduler |
Scheduler daemon and coddy_scheduler_* tools; with http, /coddy/scheduler REST |
docs/scheduler.md, external/scheduler/README.md |
cli |
Interactive console TUI — bare coddy on a terminal (or coddy cli): chat with streaming, tool boxes, permission modals, !!<command> to run a shell command locally that the agent never sees, a status bar with the NeuralDeep account usage (session and week windows, reset times, wallet), /usage for the full breakdown, and with agent.wait_for_limit_reset a turn that hits a limit waits it out and resumes by itself; coddy -c continues the latest session, coddy -p "..." runs one prompt non-interactively, **`--remote <name |
host:port |
gateway.telegram |
Telegram bot adapter — started by coddy serve when gateways.telegram.enable is true, per-user sessions, access control, live in the web UI |
docs/gateway.md |
gateway |
All messenger adapters (superset of gateway.telegram; add Discord/Slack without changing the core) |
docs/gateway.md |
Extended narrative and Docker alignment - docs/build.md.
Release images are published on GitHub Container Registry as ghcr.io/coddy-project/coddy-agent (tags such as latest and X.Y.Z, linux/amd64 and linux/arm64). Each SemVer git tag also gets GitHub Release archives (Linux, Windows, macOS Intel and Apple Silicon), Linux .deb / .rpm packages, and a Homebrew cask - see docs/build.md and docs/homebrew.md. The default image includes http, ui, scheduler, memory, cli, and gateway - the same set as make build TAGS="http ui scheduler memory cli gateway swarm".
1. Config and workspace (from the repo root, or any directory where you keep config.yaml):
cp config.example.yaml config.yaml
mkdir -p workspace coddy_home
# Edit config.yaml: at least one provider api_key (or rely on OPENAI_API_KEY etc. in compose)2. Start with Compose (pull published image, no local build):
docker compose pull
docker compose up -dTo build the image locally instead, use docker-compose.dev.yml: docker compose -f docker-compose.dev.yml up -d --build.
3. Open the bundled UI in a browser on the host:
http://127.0.0.1:12345/
The SPA is served on GET / by coddy serve. Pick a model in the composer (YAML backends from GET /v1/models), choose agent, plan, or ask mode, then send a message - the UI creates a session and streams the reply via POST /v1/responses. Agent files and shell tools use the mounted workspace (./workspace → /workspace in the container). Live YAML editing: http://127.0.0.1:12345/#/settings.
Sanity check without a browser: curl -sS http://127.0.0.1:12345/v1/models | head.
There is no login on the HTTP surface - expose port 12345 only on trusted networks. Full compose options, volumes, and CI image tags: docs/docker.md. Smoke script: examples/httpserver/docker.sh.
CODDY_HOME(orcoddy acp --home) is the agent state directory. Default~/.coddy. The process createssessions/andskills/under it. Config defaults to$CODDY_HOME/config.yaml.CODDY_CWD(orcoddy acp --cwd) is the default session working directory whensession/newsends an emptycwd. Default is the process current directory at startup. Editors that pass a path insession/newuse that path instead.
CODDY_HOME defaults to ~/.coddy. Unless you set CODDY_CONFIG or pass --config, the primary config file is config.yaml at $CODDY_HOME/config.yaml.
Copy the example and edit it:
mkdir -p ~/.coddy && cp config.example.yaml ~/.coddy/config.yamlIf $CODDY_HOME/config.yaml is absent, the loader may use config.yaml in the process working directory (useful when running from a repository clone). See docs/config.md.
Providers and models
providers- named backends (type:openaifor configurable OpenAI-compatible HTTP APIs,anthropicfor Anthropic,neuraldeepfor NeuralDeep at either of its two official endpoints,codexfor ChatGPT OAuth through the official Codex backend). Eachnamemust be ASCII letters, digits, hyphen, or underscore, starting with a letter (it becomes the prefix in model ids). API-key providers acceptapi_key(literal,${ENV}, or empty forNAME_API_KEY) and optionalapi_base. Forcodex, use Sign In with ChatGPT in the bundled web UI orcoddy providers login codexin a terminal (ACP and headless setups);api_keyandapi_baseare ignored and credentials are stored under$CODDY_HOME/providers/<name>/. The terminal login also adds the provider, the subscription models Codex lists, and anagent.modeltoconfig.yamlwhen they are missing (--no-configskips that). Codex is only a model backend - the agent keeps Coddy's own prompt, tools, and permissions, and an existingcodex loginin~/.codex/auth.jsonis picked up as a fallback. Forneuraldeep,api_basepicks the deployment -https://api.neuraldeep.ru/v1(Russia, the default) orhttps://api.neuraldeep.tech/v1(the international mirror) - and any other value falls back to the default. Sign in with your hub account instead of pasting a key:coddy providers login neuraldeepprints a short code and the hub page to confirm it on (the device flow, RFC 8628 - it works from a browser on any machine, which is what a server reached over SSH needs;--browserasks for the loopback callback instead, and only completes in a browser running on this machine;--api-basepicks the deployment, which also moves an existing row to it), stores the hub-issued key under$CODDY_HOME/providers/<name>/neuraldeep-auth.json, and adds the tier's models toconfig.yaml(--no-configskips that); the bundled web UI offers an endpoint dropdown and Sign In with NeuralDeep on the provider row. The endpoint decides which hub issues the key, so pick it before signing in; the web sign-in follows the dropdown as picked, before Save, and the row warns when a stored login came from the other deployment's hub. An explicitapi_key/api_key_command/NEURALDEEP_API_KEYstill wins over the stored login.coddy providers listshows every provider with the credential source requests actually use, andcoddy providers logout <name>revokes the key on the hub (best-effort) and forgets it locally.models- selectable models. Eachmodelstring is<provider_name>/<api_model_id>whereprovider_namematchesproviders[].name. Tunables includemax_tokens,temperature, and optionalmax_context_tokens.agent-modelpicks the default ReAct model (must match onemodels[].modelentry).max_turnsandmax_tokens_per_turnbound one user turn.loop_guard(defaulttrue) adds runaway-loop protection on top of that cap: a streamed response that degenerates into repeating the same passage is cut (loop_stream_repeat_cycles), and a tool requested over and over with identical arguments stops being executed (loop_tool_repeat_limit). The model is nudged back on track first; a turn that keeps looping afterloop_nudge_maxnudges ends with a notice.
Example (openai provider and gpt-5.4-mini; store secrets in the environment, not in git):
providers:
- name: openai
type: openai
api_key: "${OPENAI_API_KEY}"
models:
- model: "openai/gpt-5.4-mini"
max_tokens: 400000
reasoning_default: medium
agent:
model: "openai/gpt-5.4-mini"
max_turns: 35
max_tokens_per_turn: 128000Then export the key the YAML references:
export OPENAI_API_KEY="sk-..."Other setups (Anthropic, NeuralDeep, Ollama, a non-default api_base, and env-based defaults) are covered in config.example.yaml and docs/config.md.
Official CLI binaries are published on GitHub Releases (assets such as coddy_0.9.3_linux_amd64.tar.gz, plus .deb and .rpm packages for Linux). Each release matches the full feature set from make build TAGS="http ui scheduler memory cli gateway swarm".
coddy update downloads the archive for your OS/architecture and replaces the binary you invoked (symlinks resolved). That is the usual path after make install (~/.local/bin/coddy) or when you run ./build/coddy update to refresh a local build artifact.
1. See what you run today
which coddy
coddy -v2. Check for a newer release
coddy update --checkExit code 0 means you are already on the latest published X.Y.Z (or newer). Exit code 1 means a newer release is available.
3. Install
coddy update # asks [y/N]
coddy update -y # no prompt4. Confirm
coddy -v
coddy serve --help # subsystem flags; the surfaces themselves need their build tagsCommon flags
| Flag | Purpose |
|---|---|
--check |
Only report whether an update exists (no download). |
-y / --yes |
Install without confirmation. |
--version X.Y.Z |
Install a specific release, not only "latest". |
--repo owner/name |
Alternate GitHub repo (default coddy-project/coddy-agent). |
Installed from a .deb, an .rpm or Homebrew?
Coddy will not overwrite a file a package manager owns. As an ordinary user, coddy update names the command that upgrades the package and changes nothing; as root on a .deb or .rpm install, it downloads the release package for your architecture and installs it through apt-get, dnf, zypper or whichever tool the system has:
sudo coddy update -y # deb / rpm
brew upgrade --cask coddy # Homebrew cask (Caskroom)
brew upgrade coddy # Homebrew formula (Cellar)Notes
- Update the same binary you intend to use. If
which coddypoints at~/.local/bin/coddy, runcoddy updatefrom that install, not a different copy onPATH. $CODDY_HOME(config, sessions, skills) is untouched; only the executable changes.- To build from source or change tags, use
make buildinstead. For containers, usedocker compose pull. See docs/update.md for platform tables, limitations, and other upgrade paths.
Full task execution mode. The agent has access to all tools:
- Read and write files
- Execute shell commands (with permission prompt)
- Search codebase
- Call MCP server tools
Best for: code generation, refactoring, debugging, feature implementation.
Planning and documentation mode. Restricted tools:
- Read files (no write to code files)
- Write/edit text and markdown files
- Search codebase
When the plan is ready, switch to agent mode yourself for full tools and implementation.
Best for: architecture planning, writing specs, design documents, code review.
Read-only research mode. The model gets read, keep_result, glob, grep, print_tree, websearch, webfetch, question, and load_skill: no shell, no file writes, no plan or todo tools, no config tools, no MCP tools. Unlike plan mode the allowlist is also enforced when a call executes, so a tool call replayed from earlier history is refused instead of run; a @plans/... mention is read, never run; the memory copilot recalls but never saves. Deterministic operator commands typed as the prompt (/compact, /plugin) are outside this boundary.
Best for: questions about the codebase, code review and diagnosis, web research.
Switch modes from the composer selector in the web UI, /mode (or --mode agent|plan|ask) in the console, or your editor's session mode selector over ACP (session/set_config_option).
Project rules (injected as {{.Rules}}) are discovered under the session working directory from .coddy/rules, the tool-neutral .agents/rules (the rules sibling of .agents/skills), .cursor/rules, .claude/rules, .codex/rules, and nested **/AGENTS.md (agents.md convention; the root AGENTS.md is injected separately as a project docs preamble) when rules.auto_discover is true. See docs/rules.md.
The file extension selects the dialect, so one folder can hold both kinds. A .mdc file is a Cursor rule (description, comma-separated globs, alwaysApply), a .md file is a Claude Code rule (paths; loaded unconditionally when paths is absent). Both of these attach once a Go file is attached or read:
---
description: Go coding standards
globs: **/*.go
alwaysApply: false
---
Write all comments in English.
Use fmt.Errorf("context: %w", err) for error wrapping.---
description: Go coding standards
paths:
- "**/*.go"
---
Write all comments in English.
Use fmt.Errorf("context: %w", err) for error wrapping.Slash commands and SKILL.md packs (injected as {{.Skills}}) extend the agent with domain knowledge and specialized workflows.
Default directories (lowest → highest priority):
| Priority | Path | Purpose |
|---|---|---|
| lowest | ~/.agents/skills/ |
Global skills — installed by npx skills or npx skillsbd, shared with all agents |
| ↑ | ~/.coddy/skills/ |
Coddy-specific skills; may contain symlinks into ~/.agents/skills/ |
| highest | ${CWD}/.coddy/skills/ |
Project-local skills — override anything from higher directories |
Later directories override earlier ones when the same skill name appears in multiple locations.
Finding and installing skills:
- skills.sh — community registry, install with
npx skills add <owner/repo@skill> - neuraldeep.ru/skills — skillsbd registry curated for Coddy, install with
npx skillsbd install <name> - Settings → Skills in the web UI (
coddy serve) — browse and install from the skillsbd registry without leaving the browser
CLI:
coddy skills list # list installed skills with enabled/disabled status
coddy skills enable <name> # enable a skill
coddy skills disable <name> # disable without uninstallingSee docs/skills.md for the full reference.
Connect external tools via MCP servers over any transport: stdio (local
command), http (streamable HTTP with automatic legacy-SSE fallback), or
sse. Servers are configured globally in config.yaml (mcp_servers) or the
Cursor-compatible ~/.coddy/mcp.json, locally per project in
./.coddy/mcp.json (later levels override by name), or passed per-session by
the ACP client. Whole servers and individual tools can be switched off from
the config files, the /coddy/mcp* REST API, or the Settings -> MCP servers
web UI.
Example adding a GitHub MCP server in config:
mcp_servers:
- name: "github"
command: "npx"
args: ["-y", "@modelcontextprotocol/server-github"]
env:
- name: "GITHUB_PERSONAL_ACCESS_TOKEN"
value: "${GITHUB_TOKEN}"The same server in .coddy/mcp.json, plus a remote one:
{
"mcpServers": {
"github": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-github"] },
"remote-tools": { "url": "https://mcp.example.com/mcp" }
}
}The project-local ./.coddy/mcp.json arrives with the checkout, so the
repository - not you - would be choosing the command a session starts. Those
entries are therefore not started until approved for that workspace
(mcp.project_trust: ask, the default):
coddy mcp listcoddy mcp trust <name>The same decision is available at POST /coddy/mcp/{name}/trust and behind the
shield button in Settings -> MCP servers. Approval is bound to the workspace and
to a digest of the declaration, so rewriting the entry asks again. Servers in
config.yaml and ~/.coddy/mcp.json are yours and are never gated.
For a workspace you already trust (or a CI job), set mcp.project_trust: allow
in config.yaml, or pass --mcp-project-trust allow to coddy acp /
coddy serve for that process only; deny never loads project servers at all.
Added for issue #80.
See MCP Integration Guide for details.
Build with -tags gateway.telegram (Telegram only) or -tags gateway (all adapters), then set gateways.telegram.enable: true. The bot comes up with the rest of coddy serve and its chats are ordinary sessions the web UI can watch and continue.
make build TAGS="gateway.telegram"
./build/coddy serve --config ~/.coddy/config.yamlMinimal config addition (config.yaml):
gateways:
telegram:
enabled: true
token: "${TELEGRAM_BOT_TOKEN}"
admins: [YOUR_USER_ID]
default_access: "admins" # all | admins | group:<name>
default_isolation: "admin" # individual | shared | admin
rich_messages: true # Bot API 10.1 Rich Messages (native Markdown + tool blocks)Each user or chat gets its own isolated session. In group chats the bot responds only when @mentioned or replied to. /clear (no space) starts a fresh session.
With rich_messages: true the bot uses Bot API 10.1 Rich Messages: the agent's full Markdown (headings, tables, code, task lists) renders natively, tool activity streams as a "Thinking…" placeholder, and executed tools appear in a collapsible block. It falls back to legacy formatting if the Bot API server doesn't support it. See docs/gateway.md.
Full guide — access levels, group isolation modes, per-chat overrides, and how to write adapters for new messengers: docs/gateway.md.
Full configuration reference in docs/config.md; field-by-field tables in docs/config-reference.md. A JSON Schema, published at https://coddy.dev/config.schema.json, enables editor autocomplete and validation via a # yaml-language-server: $schema=... header. Coddy writes that header into every config.yaml it saves and keeps the comments already in the file (see config.example.yaml).
Key settings:
providers:
- name: local
type: openai
api_key: "${OPENAI_API_KEY}"
api_base: "${OPENAI_API_BASE}"
models:
- model: "local/gpt-5.6-terra"
max_tokens: 8192
reasoning_default: medium
agent:
model: "local/gpt-5.6-terra"
max_turns: 30
tools:
require_permission_for_commands: trueACP client (editor / script / CI) Messenger (Telegram, …)
| |
JSON-RPC 2.0 over stdio gateway Hub (per adapter goroutine)
| |
ACP Server Layer session.Manager (shared)
| |
Session Manager ─────────────────────────────┘
|
ReAct Agent Loop
/ | | \
LLM Tools Skills MCP
See Architecture docs for full details.
- Install - installer script options, Linux
.deb/.rpmpackages, the Homebrew cask, Windows paths, manual placement - Build from source - prerequisites,
make build,TAGSvsgo build -tags,build/coddy,make deb/rpm/brew/brew-formula - Homebrew - which Homebrew repository takes what, the cask against the formula, and the homebrew/core submission
- Updating Coddy -
coddy update, release assets,PATHvsmake install - Docker - GHCR image,
docker compose, bundled UI athttp://127.0.0.1:12345/ - Daemon -
coddy serve --daemon,status/stop/restart, restart pacing, and how a configuration change made elsewhere reaches a running process - Console TUI - bare
coddyin a terminal (-tags cli): layout, keys, flags, print mode, captures - Remote control - driving a remote
coddy serveserver from the console, ACP, or the web UI - Architecture - system design and component overview
- ACP Protocol - protocol reference and message formats
- ReAct Agent - ReAct loop design and tool specifications
- Configuration - full config file reference; field tables and JSON Schema for editor validation
- HTTP API - REST gateway (
-tags=http) and embedded UI (-tags=http,ui); includes/coddy/configfor live YAML editing from the SPA (#/settings). - Embedded UI - functional spec, Vite dev workflow, build tags
- DESIGN.md - UI tokens and layout (English)
- AGENTS.md - repo map and contributor notes for automation
- Rules - project rules (
.cursor/rules,.coddy/rules, …) - Codex hooks - how
.cursor/rules/*.mdcreach a Codex CLI session working on this repo - OpenCode hooks - deterministic delivery of
.cursor/rules/*.mdcto OpenCode sessions working on this repo - Skills - slash commands and
skills.dirs - Session export - the
/exportcommand: formats, path rules, trimming options, the JSON document - Custom tools - adding a tool to the registry, schema, and permission wiring
- Scheduler - cron job files, UTC firing rules, run sessions, and the
coddy_scheduler_*tools - ZCode hooks - deterministic delivery of
.cursor/rules/*.mdcto ZCode sessions working on this repo - Background tasks - detached commands, the task pool, timeouts, and program-wide permission grants
- Subagents - definition files, project trust receipts, the
spawn_agenttool, capability narrowing, child sessions - Hooks - lifecycle hooks: definition files, matchers, the stdin payload and the exit-code/JSON answer, project trust
- MCP Integration - MCP server integration guide
- Messenger Gateway - Telegram bot adapter, session isolation, ACL, and how to write new adapters
examples/acp/acp_e2e_todo.py is a newline-delimited JSON-RPC harness against coddy acp ( stdbuf -oL, permission auto-reply, nil-result responses). Use it as reference when building your own minimal client rather than chaining naive echo lines into a pipe.
examples/acp/acp_e2e_memory.py drives build/coddy, an isolated CODDY_HOME, and RPA_API_KEY to verify recall, persist, and optional prune of markdown under $CODDY_HOME/memory. See the script docstring for flags. Overview of all harnesses - examples/README.md.
By default, coddy acp and coddy serve store each session bundle under $CODDY_HOME/sessions/<sessionId>/ (default ~/.coddy/sessions/) with session.json, messages.json, an assets/ directory, and todos/active.md (plus todos/archive/ when completed lists are replaced). Override the root with coddy acp --sessions-dir, coddy serve --sessions-dir, or sessions.dir in config.yaml. If the sessions directory cannot be created, startup fails with an error.
coddy sessions listprints stored sessions (--sessions-dirand--cwdfilters supported)./exportin any chat writes the current transcript tocoddy-export-<timestamp>.md(orhtml,json,jsonl, or a path you name) inside the workspace;coddy sessions export <id> [--format ...] [--out PATH]does the same for a stored session from the shell, into the current directory or wherever--outpoints - see Session export.coddy acp --session-id <id>makes the nextsession/neweither reopen snapshots for that folder (if present) or create a fresh bundle whose directory name matches that id.session/loadrestores history and notifies the client;session/listlists bundles for ACP-aware clients.
The coddy todo tools keep the active checklist mirrored to todos/active.md. A wholesale coddy_todo_plan_replace while items are incomplete is rejected until you finish rows or run coddy_todo_plan_archive; replacing when every row is completed moves the prior active.md into todos/archive/ (todo-<nanos>.md). coddy_todo_plan_archive finishes open rows to completed, writes todos/archive/plan_<unix_seconds>.md, then clears the session plan when persistence is on.
When the persisted plan is non-empty, the agent injects ### Current todo checklist plus rendered markdown checklist lines into the system prompt template (embedded defaults, or files under prompts.dir using prompts.agent_prompt / prompts.plan_prompt / prompts.ask_prompt, which default to agent.md / plan.md / ask.md) via {{if .TodoList}} … {{end}}. That block is omitted when there is nothing to track. Before each LLM call inside one session/prompt turn, Coddy refreshes that system message so a todo list created or updated earlier in the same ReAct episode stays visible immediately.
The Makefile is the entry point for local builds and tests. Its default goal is build.
| Target | What it does |
|---|---|
make / make build |
Build build/coddy with the current TAGS (see Build tags). With http+ui it first runs ui-build (installs and bundles the embedded SPA). |
make build TAGS="…" |
Same, choosing modules. Full binary (Docker defaults): make build TAGS="http ui scheduler memory cli gateway swarm". Lean ACP-only binary: make build (no tags). |
make ui-build |
Install external/ui deps and produce the embedded SPA assets consumed by the ui tag. |
make test |
Run go test across the tag combinations (default, http, scheduler, ui, and mixes) plus ui-build. |
make lint |
Run golangci-lint run ./... (requires golangci-lint). |
make install |
Copy build/coddy to ~/.local/bin (or /usr/local/bin for root); builds TAGS="http ui scheduler memory cli gateway swarm" first if the binary is missing. |
make print-version |
Print the embedded version string (git tag/describe, else dev). |
make clean |
Remove the build/ directory. |
TAGS uses spaces (make build TAGS="http ui scheduler memory cli gateway swarm"); a raw go build uses commas (-tags=http,ui,scheduler,memory).
Windows note. The
Makefiletargets need a Unix-like shell — run them from Git Bash (or WSL/MSYS2), notcmd/PowerShell. Building with theuitag also requires Node.js/npm onPATH. Ifmake ui-build(ormake build TAGS="…ui…") fails withnpm error enoent … open '…\package.json', you are on an npm that mishandles--prefix; build the UI from inside its directory instead:(cd external/ui && npm install && npm run build:go) make build TAGS="http ui scheduler memory cli gateway swarm" # ui-build now sees the prebuilt assets
# Run tests
go test ./...
make test
# Example harnesses (see examples/README.md): ./examples/build_coddy.sh && ./examples/test_acp.sh && ./examples/test_httpserver.sh
# Full-featured local binary (HTTP + UI + scheduler), same defaults as Docker
make build TAGS="http ui scheduler memory cli gateway swarm"
./build/coddy -v # same as --version
# Run with debug logging (ACP mode); optional --log-output, --log-file, --log-format
coddy acp --log-level debug
# Single-line sanity check only (responses may omit JSON-RPC "result" for nil payloads; prefer examples/acp/acp_e2e_todo.py)
echo '{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"protocolVersion":1,"clientCapabilities":{}}}' | coddy acpUI-only iteration (SPA hot-reload against a running backend) is described in DESIGN.md → Dev workflow.
This project is licensed under the MIT License, see the LICENSE file in the repository root for details.













