Skip to content

Latest commit

 

History

910 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Go 1.25+ MIT License Tests on PR Latest release ACP harness distroless-ready single binary

Coddy agent

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)
Start screen Mobile start
More screenshots
Chat Mobile chat
Chat Mobile chat
History Scheduler
History Scheduler
Scheduler — job editor Settings
Scheduler job editor Settings
Settings — Skills Settings — Appearance
Settings Skills Settings Appearance
Settings - MCP servers (project trust gate) Background tasks
Settings MCP 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:

Console startup

Console turn with a tool call

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.

Contents

Features

  • Harness-first - ACP server, session lifecycle, prompts, LLM backends, MCP merge, distroless-ready binary
  • One process, every surface - coddy serve runs whatever config.yaml enables: 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 --daemon puts it in the background under a dispatcher that starts it again when it dies, watches config.yaml so 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 | restart drive it. Bare coddy is the interactive console (-tags cli) and coddy acp serves editors; all of them share $CODDY_HOME sessions - 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), and ask (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 (.mdc Cursor, .md Claude Code) - see Rules
  • Skills - slash commands and SKILL.md packs from skills.dirs (defaults: ~/.agents/skills, ~/.coddy/skills, ${CWD}/.coddy/skills; later dirs override earlier) - see Skills
  • Background tasks - run_command can run detached (background: true plus the model's own expected_seconds estimate); background_list / background_output / background_wait / background_stop collect 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/agents and .coddy/agents (Claude Code's .claude/agents load 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 PreToolUse hook can deny a tool call whatever the permission mode, approve it past the prompt, rewrite its arguments or add context, a PostToolUse hook can run a formatter or an audit log, UserPromptSubmit can reject a prompt, Stop can keep the agent working until a checklist is done, SessionStart adds context to every prompt, PreCompact can veto a compaction, SubagentStart can refuse a delegation and Notification can ping you when a permission prompt is waiting; definitions use Claude Code's hooks.json shape (~/.coddy/hooks.json, .coddy/hooks.json, and the workspace's .claude/settings*.json load 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 reaches compaction.threshold_percent (default 80%) of the model's max_context_tokens; the last compaction.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-tools and --no-thinking trim it to the chat text - see Session export
  • Multimodal / file attachments - attach images and files via the composer (📎) when multimodal: true in 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 OpenAI reasoning_effort or Anthropic extended-thinking budget_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_command tool runs commands on remote hosts over pure-Go SSH (no external binary); authenticates via SSH agent (SSH_AUTH_SOCK) or ~/.ssh key 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

Editor and IDE integration

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/.

Quick Start

Install

Linux / macOS - release binary plus ~/.coddy bootstrap:

curl -fsSL https://coddy.dev/install.sh | bash

Windows (PowerShell)

irm https://coddy.dev/install.ps1 | iex

Creates ~/.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 select pwsh, then Windows PowerShell, then cmd.exe; Unix builds select bash, then sh. The installing terminal does not see the updated PATH — 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.rpm

macOS - the same release publishes a Homebrew cask:

brew install --cask https://github.com/coddy-project/coddy-agent/releases/latest/download/coddy.rb

brew 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 http and ui (the Makefile runs ui-build for embedded assets).

Install with Go (lean module default, no http / UI tags)

go install github.com/EvilFreelancer/coddy-agent/cmd/coddy@latest

For 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/bin

Or 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.).

Build tags

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.

Docker

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 -d

To 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.

Paths (CODDY_HOME, CODDY_CWD)

  • CODDY_HOME (or coddy acp --home) is the agent state directory. Default ~/.coddy. The process creates sessions/ and skills/ under it. Config defaults to $CODDY_HOME/config.yaml.
  • CODDY_CWD (or coddy acp --cwd) is the default session working directory when session/new sends an empty cwd. Default is the process current directory at startup. Editors that pass a path in session/new use that path instead.

Configuration

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.yaml

If $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: openai for configurable OpenAI-compatible HTTP APIs, anthropic for Anthropic, neuraldeep for NeuralDeep at either of its two official endpoints, codex for ChatGPT OAuth through the official Codex backend). Each name must be ASCII letters, digits, hyphen, or underscore, starting with a letter (it becomes the prefix in model ids). API-key providers accept api_key (literal, ${ENV}, or empty for NAME_API_KEY) and optional api_base. For codex, use Sign In with ChatGPT in the bundled web UI or coddy providers login codex in a terminal (ACP and headless setups); api_key and api_base are ignored and credentials are stored under $CODDY_HOME/providers/<name>/. The terminal login also adds the provider, the subscription models Codex lists, and an agent.model to config.yaml when they are missing (--no-config skips that). Codex is only a model backend - the agent keeps Coddy's own prompt, tools, and permissions, and an existing codex login in ~/.codex/auth.json is picked up as a fallback. For neuraldeep, api_base picks the deployment - https://api.neuraldeep.ru/v1 (Russia, the default) or https://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 neuraldeep prints 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; --browser asks for the loopback callback instead, and only completes in a browser running on this machine; --api-base picks 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 to config.yaml (--no-config skips 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 explicit api_key / api_key_command / NEURALDEEP_API_KEY still wins over the stored login. coddy providers list shows every provider with the credential source requests actually use, and coddy providers logout <name> revokes the key on the hub (best-effort) and forgets it locally.
  • models - selectable models. Each model string is <provider_name>/<api_model_id> where provider_name matches providers[].name. Tunables include max_tokens, temperature, and optional max_context_tokens.
  • agent - model picks the default ReAct model (must match one models[].model entry). max_turns and max_tokens_per_turn bound one user turn. loop_guard (default true) 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 after loop_nudge_max nudges 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: 128000

Then 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.

How to update

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 -v

2. Check for a newer release

coddy update --check

Exit 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 prompt

4. Confirm

coddy -v
coddy serve --help     # subsystem flags; the surfaces themselves need their build tags

Common 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 coddy points at ~/.local/bin/coddy, run coddy update from that install, not a different copy on PATH.
  • $CODDY_HOME (config, sessions, skills) is untouched; only the executable changes.
  • To build from source or change tags, use make build instead. For containers, use docker compose pull. See docs/update.md for platform tables, limitations, and other upgrade paths.

Operating Modes

Agent Mode (default)

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.

Plan Mode

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.

Ask Mode

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).

Rules

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.

Skills

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 uninstalling

See docs/skills.md for the full reference.

MCP Server Integration

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 list
coddy 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.

Messenger gateway

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.yaml

Minimal 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.

Configuration

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: true

Architecture

ACP 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.

Documentation

  • Install - installer script options, Linux .deb / .rpm packages, the Homebrew cask, Windows paths, manual placement
  • Build from source - prerequisites, make build, TAGS vs go 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, PATH vs make install
  • Docker - GHCR image, docker compose, bundled UI at http://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 coddy in a terminal (-tags cli): layout, keys, flags, print mode, captures
  • Remote control - driving a remote coddy serve server 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/config for 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/*.mdc reach a Codex CLI session working on this repo
  • OpenCode hooks - deterministic delivery of .cursor/rules/*.mdc to OpenCode sessions working on this repo
  • Skills - slash commands and skills.dirs
  • Session export - the /export command: 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/*.mdc to 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_agent tool, 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 over stdio)

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.

Persistent sessions

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 list prints stored sessions (--sessions-dir and --cwd filters supported).
  • /export in any chat writes the current transcript to coddy-export-<timestamp>.md (or html, 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 --out points - see Session export.
  • coddy acp --session-id <id> makes the next session/new either reopen snapshots for that folder (if present) or create a fresh bundle whose directory name matches that id.
  • session/load restores history and notifies the client; session/list lists 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.

Development

make targets

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 Makefile targets need a Unix-like shell — run them from Git Bash (or WSL/MSYS2), not cmd/PowerShell. Building with the ui tag also requires Node.js/npm on PATH. If make ui-build (or make build TAGS="…ui…") fails with npm 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

Common commands

# 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 acp

UI-only iteration (SPA hot-reload against a running backend) is described in DESIGN.mdDev workflow.

License

This project is licensed under the MIT License, see the LICENSE file in the repository root for details.

About

General-purpose agent in one static Go binary. ReAct loop, ACP server for IDEs, OpenAI-compatible REST API with embedded web UI, Telegram gateway, cron scheduler, long-term memory, context compaction, rules, skills, MCP. Distroless-ready, works with any OpenAI-compatible provider.

Topics

Resources

Stars

138 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages