cordy 0.2.0

A cross-platform TUI coding agent in Rust — workspace tabs, PTY terminals, direct-key panels, hot-swap any model/provider mid-conversation, MCP, skills, sub-agents and background jobs.
cordy-0.2.0 is not a library.

English · Русский

Hot-swap any model or provider mid-conversation. Edit files behind a permission gate. MCP, skills, sub-agents, and background jobs — in one fast, keyboard-driven TUI.

CI Release crates.io License: MIT Rust

Cordy is a cross-platform terminal agent that talks to every major API family — OpenAI Chat Completions, OpenAI-compatible endpoints, Anthropic Messages, and the OpenAI Responses API — through one canonical model, so switching provider or model never loses your conversation. It edits files with an exact, diff-confirmed edit, runs a builtin toolset whose command output is compressed by a native token optimizer, and speaks the Model Context Protocol.

  • Hot-swap models & providers mid-conversation — start on a local model, finish on a frontier one, context intact. ^P → pick a model, or /connect to add a provider.
  • Every API family — OpenAI Chat, OpenAI-compatible (Ollama / vLLM / OpenRouter / Groq / …), Anthropic Messages, OpenAI Responses. Wire formats never leak past the adapter.
  • Builtin toolsread write edit apply_patch multiedit grep glob ls bash todo web_search web_fetch process rewind, all behind a permission gate you can pre-approve with globs. apply_patch applies a multi-file, multi-hunk patch as one reviewed unit, matching context tolerantly so near-miss whitespace and smart quotes still land.
  • Background jobs — run a dev server with bash background:true, then process to poll, wait on a regex, or kill the whole process tree.
  • MCP, skills, sub-agents — connect MCP servers, load progressive-disclosure skills, and delegate work to isolated sub-agents via the task tool.
  • Free web search — DuckDuckGo out of the box (no key), or Exa when EXA_API_KEY is set.
  • Workspace tabs — up to five per project, each with its own session, model, mode, cost counters, undo checkpoints and history. Background tabs keep streaming; the strip badges what changed, and Cordy warns when two tabs write the same file.
  • Direct-key panels^D mode · ^L model · ^G git · ^S skills · ^K context · ^T terminal · ^E editor · ^B tabs. One overlay, one look, keyboard all the way down.
  • Real terminals in the UI^T opens a PTY panel beside the chat (shell, test watcher, or a full-screen editor via ^E), resizable and focus-switchable without leaving Cordy.
  • Modes that actually bindbuild plan architect socratic challenge review. Each injects its own contract into the system prompt, and the read-only ones are enforced by permission rules, not just asked for politely.
  • Steer a running turn^Alt+S (or /steer …) drops a correction into the turn that is already in flight, so you redirect the agent instead of aborting and starting over.
  • Live cost & context HUD — a header bar with git state, context meter and model chip; a context inspector that breaks the next request down by section; and a model-events log with per-call latency, tokens and cost.
  • 42 themes, hot-reloaded — plus custom themes as JSON in ~/.cordy/themes/, re-read the moment you save them.

Linux / macOS

curl -fsSL https://raw.githubusercontent.com/redstone-md/Cordy/main/install.sh | sh

Windows (PowerShell)

irm https://raw.githubusercontent.com/redstone-md/Cordy/main/install.ps1 | iex

The scripts download the signed binary for your platform, verify its checksum, and drop cordy on your PATH.

With cargocargo install cordy

Prebuilt binaries — or grab the archive for your platform from the latest release, unpack, and run cordy.

From source (Rust 1.88+) — the default build is full-featured (MCP included):

git clone https://github.com/redstone-md/Cordy.git
cd Cordy
cargo build --release
# binary at target/release/cordy

Want a leaner binary without the MCP client? cargo build --release --no-default-features.

Point Cordy at any OpenAI-compatible endpoint via environment variables, then run it:

export OPENAI_API_KEY=sk-...
export CORDY_BASE_URL=https://api.openai.com/v1   # or any compatible endpoint
export CORDY_MODEL=gpt-4o-mini
cordy

…or skip the env vars and press ^P → /connect inside the app to add a provider through the wizard. Providers you connect are saved to ~/.cordy/config.toml, and the last one is restored on launch. All user state — config, keys, sessions, cache — lives under ~/.cordy.

Panels

Key Action
^D · ^L mode / persona · model picker
^G · ^S git menu (status, diff, log, commit, push, stash) · skills browser
^K · ^P context inspector · command palette
^T · ^E terminal panel · editor panel ($EDITOR)

Tabs

Key Action
^N · Alt+W new tab · close tab
Alt+1Alt+5 · ^B focus tab · tab list

Terminal panel (while focused)

Key Action
^Alt+T · ^Alt+W back to the chat · close the panel
^Alt+N · ^Alt+↑/ next panel · resize

Composer

Key Action
Enter send · ^J / Alt+Enter newline
Tab / Shift+Tab cycle agent/mode
/ move across lines · scroll the transcript · then prompt history
^↑ / ^↓ prompt history, always
PgUp/PgDn · Home/End page the transcript · jump to top/bottom
Esc · ^Alt+S interrupt the turn · steer it instead
^X then … leader: l sessions · m models · t theme · s status · y copy reply · g top · z redraw
^R · ^-/^. rename session · undo/redo input

Slash commands include /connect /providers /model /tabs /context /events /term /git /steer /sessions /permissions /compact /goal and more — type / to autocomplete.

Two bindings differ from stock readline: ^E opens the editor panel (line-end moved to Alt+E and End), and ^D opens the mode picker (quit is ^C on an empty line, ^X q, or /quit).

Clickable

The bottom row is a menu bar, not a cheat sheet: every hint is a button, and so are the header's model / branch / context / spend chips, the tab strip, and every picker row. Clicking a tool row unfolds its full output. The mouse is captured for this, which costs plain drag-select — Shift+drag still selects, and ^X M (or the indicator, /mouse, mouse = false in config) hands the mouse back to the terminal entirely.

Pasting is your terminal's own paste; Alt+V pastes an image from the clipboard.

Seeing the UI without running it

cordy render list                 # scenario names
cordy render git 120x30           # draw one, in color
cordy render chat 110x30 --plain  # …or as plain text, for diffing

A goal is an objective the session keeps working on by itself. While it is active, each finished turn feeds the next one, so a long task runs unattended until it is done, out of budget, or stuck.

/goal fix the flaky auth test --budget 200k --cost 2.50 --turns 20
/goal                 # status: objective, tokens, elapsed
/goal edit            # load the objective back into the composer
/goal pause           # stop the loop, keep the goal
/goal resume          # back to work
/goal clear           # drop it

Budgets are the safety rail: whichever of tokens, dollars or turns runs out first flips the goal to limited by budget, and the model is told to wrap up rather than start new work. It stops on its own too — the agent marks the goal complete only after auditing the objective against the current worktree, or blocked after the same obstacle recurs three turns running. Esc or typing anything interrupts the loop; a resumed session waits for you before spending again. Defaults live under [goal] in the config, and the goal travels with the session (including forks).

~/.cordy/config.toml (merged with a project-level .cordy/config.toml). It is hot-reloaded — edits apply within a second, no restart. Secrets never live here; API keys go in the OS env or ~/.cordy/keys.json (written by /connect).

optimize = true
theme = "tokyonight"   # cordy (default) · 42 builtins, or your own JSON in ~/.cordy/themes/

# Fine-tune any role color on top of the theme
[colors]
accent  = "#7aa2f7"
surface = "#24283b"

# Autonomous goals: whichever cap is hit first ends the run
[goal]
enabled      = true
token_budget = 200000
cost_cap_usd = 5.0
max_turns    = 20

# Pre-approve commands so the agent stops asking
[permissions]
mode  = "ask"          # or "auto"
allow = ["bash:ls *", "bash:git *", "bash:cargo *"]
deny  = ["bash:rm -rf *"]

# A provider (secrets stay in env / keys.json, never here)
[[provider]]
name = "openai"
kind = "openai-chat"
base_url = "https://api.openai.com/v1"

# An MCP server (in the default build)
[[mcp]]
name = "browsermcp"
transport = "stdio"
command = "npx @browsermcp/mcp@latest"
enabled = true
src/
  core/       canonical model (ContentBlock/Message/WireEvent), agent loop, prompt, context,
              sessions, permissions, goals (autonomous loop), auth
  provider/   Provider trait + one adapter per API family (+ retry decorator)
  tools/      Tool trait, builtins, native output optimizer, sub-agents, background jobs
  skills/     progressive-disclosure skill loader
  agents/     sub-agent registry
  mcp/        MCP client (on by default; opt out with --no-default-features)
  config/     TOML load/merge, model & provider profiles
  tui/        ratatui MVU app — model/update/view, chrome (header, tabs, status),
              overlay pickers, PTY terminal panels, themes, markdown

Contributions are welcome — see CONTRIBUTING.md. Before opening a PR:

cargo fmt
cargo clippy --all-targets
cargo test

Released under the MIT License.