An AI coding agent for the terminal, built in Rust.
ragent is a Rust coding agent inspired by RooCode, Claude Code, Copilot CLI and OpenCode. It provides multi-provider LLM orchestration, a comprehensive built-in tool system, a terminal UI, and a client/server architecture — all compiled into a single statically-linked binary with zero runtime dependencies.
It is implemented in Rust as a learning exercise for the author.
Start with TUI-QUICKSTART.md to run it, or QUICKSTART.md for the guided tour.
- Multi-provider LLM support — Anthropic, OpenAI (Chat Completions and the Responses API), Google Gemini, Hugging Face, GitHub Copilot, xAI, Ollama (local and cloud), Generic OpenAI-compatible endpoints, Azure AI Foundry, Azure Resource (File), Amazon Bedrock, OpenRouter, and a Model Router cluster — 15 registry entries behind an extensible provider trait
- Local-first defaults — when no model is explicitly configured, ragent resolves to the first available local/self-hosted provider (e.g. Ollama) rather than hard-wiring a cloud provider
- Pluggable execution backends — select where a session's tools run without
changing the agent loop:
local(host, the default),docker/podman(a per-session container whose workspace is a named volume, never a host bind mount), andremote(drive a second ragent server over REST+SSE and mirror its events locally). A durable backend registry reports each backend's health, the TUI/backendswitcher shows and changes the active backend, sandbox credentials are resolved from the encrypted store at spawn time and injected as container environment variables, and a provisioning failure fails the turn rather than falling back to the host. The 7-layer bash validation, path containment, and permission system are unchanged and apply before any backend dispatch - LLM security analyzer — an opt-in permission mode (
/security on, or thesecurity_analyzerconfig block) where each proposed tool action is judged by an LLM that returns anallow/ask/denyverdict with a rationale, published before the action is permitted or refused; it is a tightening-only layer over the static rules (adenyis hard, anallownever overrides an explicit policydeny, and any analyzer failure degrades to the normal interactive prompt) - Comprehensive tool system — 148 registered tools across 21 categories in
the default build (the engine-gated
mf_screenshottool registers only when a drivable headless browser is present, taking the count to 149 — specopenhandsFR-029).ragent run --dry-runprints the live per-category counts; the groups are:
- File (27) — read, write, create, edit, multiedit, apply_patch, patch, rm,
move, copy, mkdir, append, file_info, diff, glob, list, grep, the
update_filealias, get_env, the PDF pair (pdf_read,pdf_write), the structured-memory trio (memory_store,memory_recall,memory_forget), plusconversation_searchandsession_search. Read-only tools requirefile:read; mutating tools requirefile:write - Bash (3) — bash, bash_reset and the
run_codealias. Bash carries 7-layer security: safe-command whitelist, banned commands, denied patterns, directory-escape prevention, syntax validation, obfuscation detection, and user allowlist/denylist- Bang commands — prefix any prompt with
!(e.g.! ls -la) to run a shell command directly; the output is sent to the model for review and error resolution
- Bang commands — prefix any prompt with
- Shell (1) — open (cross-platform file/URL reveal)
- Web (5) — webfetch, websearch, mf_fetch, mf_search, mf_crawl
(
mf_searchruns the keyless DuckDuckGo, Brave, OpenAlex and Wikipedia backends in parallel, plus LangSearch / Tavily / Perplexity / Exa when configured) - Code intelligence (10) — codeindex_search, codeindex_symbols, codeindex_references, codeindex_dependencies, codeindex_status, codeindex_reindex, codeindex_explain, codeindex_path, codeindex_communities, codeindex_godnodes (read-only, hardwired always-allowed)
- Git (18) — git_status, git_log, git_diff, git_branch, git_show, git_remote, git_tag, git_add, git_reset, git_checkout, git_commit, git_stash, git_cherry_pick, git_push, git_pull, git_fetch, git_clone, git_merge
- GitHub (11) and GitLab (19) — issues, PRs/MRs, pipelines, jobs, and CI/CD
- Teams (19) — the full team lifecycle, shared tasks, mailbox messaging, and coordination surface
- Agent (4) — new_agent, cancel_agent, list_agents, wait_agents
- Spec (5) — spec_list, spec_read, spec_search, spec_task_update, spec_coverage
- Task (4) — task_create, task_update, task_get, task_list
- Cron (5) — cron_add, cron_remove, cron_list, cron_enable, cron_disable
- Plan (2) — plan_enter, plan_exit
- None (8) — calculator, think, agent_complete, ragent_info (running version,
build time, git commit, compiler, plus this instance's pid, uptime, memory and
thread count), os_info (read-only host report: OS identity and Linux
distribution, CPU, graphics adapters and graphics-API versions, physical
hardware, memory, uptime, and process environment; also
/osinfo show), tool_info and commands_info (registry and slash-command dumps) - One each: model (model_info), network (http_request), system (mf_version, mf_cache_clear), skill (skill_manage), storage (initiative), ask_user (ask_user)
- MCP — mcp_tool (McpToolWrapper) for external Model Context Protocol servers, plus the dynamically registered per-server bridge tools
- Terminal UI — full-screen ratatui interface with provider setup dialog,
slash-command autocomplete, agent cycling, streaming chat with markdown and syntax
highlighting, step-numbered tool calls with pretty-printed JSON in the log panel,
a live permission countdown timer (120-second timeout with EXPIRED state), and a
message input queue (
Alt+Qmenu //queue) that keeps the input field editable while the agent executes; side panels for context (Alt+C), memory (Alt+M), telemetry (Alt+O) and tasks (Alt+T). Every list-bearing/providerand/modelstep shares one list composition with the plugin and connector catalogues - accent frame, heading count, pinned column band, zebra rows, muted key-hint footer - and windows around its cursor (Showing a-b of N) so a long provider, model, thinking-level, Azure-resource or router-bucket list never clips away the highlighted row; a mouse notch over an open setup dialog steps the cursor exactly likeUp/Downand is swallowed elsewhere - HTTP server — axum-based REST + SSE API so any frontend can drive the agent
- Session management — persistent conversation history stored in SQLite; list, resume, export-archive, and import sessions
- Permission system — multi-layered defense-in-depth with hardwired rules (codeindex tools always allowed), configurable allow/deny/ask rules, 7-layer bash security, file-path guards, and YOLO mode for trusted environments
- Agent presets —
general,build,plan,explore,askand the internaltitle/summaryhelpers, plus language and domain specialists (rust-coder,python-coder,typescript-coder,fastapi-agent,security-auditor,test-writer,documenter,devops-agent,database-agent,frontend-agent) with tailored system prompts - Custom agents — user-defined agents via JSON (OASF format) or Markdown profiles
- Project guidelines — auto-loads
AGENTS.mdfrom the project root (and~/.local/share/ragent/) into the system prompt so agents follow project-specific conventions - MCP client — Model Context Protocol support with auto-discovery of 18 known
server types, stdio and Streamable-HTTP clients, and tool bridging; TUI commands
(
/mcp//mcp status,/mcp config,/mcp discover,/mcp connect <id>,/mcp disconnect <id>) with durable global enable/disable state (mcp_state.json) and live connect/disconnect./mcp configreports where ragent looks for MCP definitions (ragent-native, npm global,PATH, and the Claude/Cline/XDG registry directories), the count found at each location, and the servers discovered
- ACP integration — Agent Client Protocol support in both directions: an ACP
client that drives Claude Code, Codex, or Gemini CLI as an external
subprocess over JSON-RPC on stdio, and a feature-gated, off-by-default ACP
server (
cargo build --features acp-server;ragent acp-server) that an ACP-capable editor (Zed, VS Code, JetBrains) attaches to, streaming the driven session's updates back assession/updatenotifications - Snapshot & undo — file snapshots before edits so changes can be rolled back
- Event bus — internal tokio pub/sub for real-time UI updates across all components
- Background agents — spawn and run multiple sub-agents concurrently for parallel
task execution, with REST API and TUI monitoring;
/spawn <agent> <prompt>launches a detached fire-and-forget sub-agent that nothing ever waits on (nolist_agentsentry, not awaitable viawait_agents, result never injected into the chat); every completed sub-agent run (detached or not) also writes its FULL output tolog/subagents/<task-id>.md, and the completion event carries the real loopfinish_reason(stop/truncation/length/cancelled/error) so a provider-side cut is flagged in the Agents panel instead of looking like a healthy finish - Agent and Team Member panel — the
AgentsandTeamsbuttons beside the message input open live control popups: the Agents window lists the primary agent and an ancestor-indented sub-agent tree with status, elapsed time, and step count plus a background-shell section; the Teams window lists the lead and every teammate with focus markers, live status, and counters; a single-row teammate strip sits under the status bar. Both windows are keyboard-first: a block cursor moves withUp/Down/PgUp/PgDn,Spacetoggles suspend/resume,Del/Shift+Karms the kill/shutdown confirmation modal,Enteropens the row's output view, and clicking a row selects it (the[stop]/[x]glyphs are status indicators only); windows scroll with the wheel, re-status live from sub-agent and team events, and closure isEsc(no window carries a Close button - the footer legend names the key); suspension is cooperative - the parked sub-agent finishes its in-flight LLM call or tool before idling (specagentui) - Prompt inspector —
/promptrenders the assembled system prompt an agent would receive (primary or subagent mode, per-agent override, roster) with the effective tool surface — read-only, no LLM call - Tool-repeat guard — after five consecutive identical tool calls the sixth is held for confirmation in interactive runs and auto-denied in unattended runs, so agent loops cannot hang replaying the same call (FR-044)
- Code index — automatic codebase indexing with tree-sitter parsing (14 grammars
covering 50 language ids), full-text search via Tantivy, incremental updates via
file watcher, and LLM-accessible tools; supports Rust, Python,
TypeScript/JavaScript, Go, C/C++, Java, Kotlin, OpenSCAD, Terraform, HCL, CMake,
Gradle (Groovy and KTS), Maven, and XML; enable/disable via
/codeindex on|off, language filtering via/codeindex lang <language>; semantic code graph withcodeindex_godnodes(top-N most-connected symbols),codeindex_path(shortest path between symbols),codeindex_explain(node metadata and edges), andcodeindex_communities(community detection); graph built in the background via/codeindex graph build(phased lock discipline keeps search available during derivation; status-baridx/graphbusy indicators show progress) - Memory system — three-tier system with file blocks, structured SQLite store, and optional embedding-based semantic search; automatic extraction, decay, compression, and knowledge graph support
- Spec management —
/specslash commands for creating, listing, searching, validating, and tracking specification lifecycles;/spec jtbdperforms Jobs-To-Be-Done analysis on existing specs;/spec updateregeneratesPLAN.mdandTESTPLAN.mdfrom an editedSPEC.md;/spec createalso emits a manualTESTPLAN.mdtest-plan artifact;/spec govcreateturns a system architecture document (URL or local file/folder) into a project, and/spec reverse <owner/repo | URL>fetches a public repo's metadata, root file tree, and README via the GitHub API, then asks the currently selected LLM model to generate a synthetic creation prompt. With the/newscaffold flags (--language <lang> --type <type> [--stack <name>]) the reverse prompt is steered towards a target language, app type, and framework stack, and--folder <path>scaffolds a real project (default: the current directory) while--github/--gitlabcreate a private remote and push it;--create <name>chains into/spec createto auto-generate a spec from the reverse-engineered prompt, written under the scaffolded project (<folder>/specs/<name>/) when--folderwas used - Project scaffolding —
/new --language <lang> --type <type>scaffolds a new project in an empty directory: the ragent workspace (.ragent/,specs/,log/,.gitignore,AGENTS.md), a runnable hello-world artifact set for 26 application languages (rust, python, go, typescript, ...) with library/cmdline/tui/gui layouts (plus a webapp HTTP server for the five web languages) plus sample-document stubs for 20 data, markup, and build formats (json, yaml, sql, cmake, maven, ...) covering every codeindex scanner language, optional stack layers (--stack axum), starter docs (README.md,QUICKSTART.md,STATS.md,docs/), git init + initial commit, and optional GitHub/GitLab remote creation + push (--github/--gitlab); progress streams live in the message window; also available as theragent newCLI subcommand - Research system —
/researchslash command family andragent researchCLI for structured information gathering (web search + local file cross-referencing) with self-containedRESEARCH.mdoutputs andGET/POST/DELETE /researchHTTP endpoints; concept/finding output limits (--max-concepts/--max-findings,research.max_concepts/research.max_findings), scholarly-engine control (scholarly backends are excluded by default;--papersincludes them,research.exclude_academic_enginespersists the exclusion), open-access toggles (--oa-enable/--no-oa), URL cloaking (--url-cloak) that defangs web source URLs in theSourcesbullets andReferences Indexso scanners do not flag them, a per-engine progress table that breaks exclusions and fetch failures out by reason/cause, andmf_searchexclude_engines - Skills system — loadable skill packs (bundled or custom YAML) that inject tools,
prompts, and file context into agent sessions; also discovers the AgentSkills
convention (
.agents/skills/project and~/.agents/skills/user, a directory per pack with aSKILL.mddeclaringnameanddescription), listable via/skills(or/skill) and loadable via/skill <name> [args]or the bare/<name>trigger, with an existing higher-scope pack winning a name clash - Plugin system — load Codex-dialect (
codex-plugin.jsonor the nested.codex-plugin/plugin.jsontheopenai/pluginsstore ships) and Claude Code/Desktop-dialect (.claude-plugin/plugin.json) plugins — including multi-target trees that ship both nested manifests side by side (e.g.mongodb/agent-skills), which resolve to the Claude dialect — run their JavaScript entries on an embedded, budget-sandboxed engine (rquickjs, no Node/Deno required) behind a versionedragenthost API, and register their tools (plugin_<id>_<tool>) and slash commands; skill-only/MCP-only plugins (no JavaScript entry) install and load inertly, and theirskillsdirectories andmcpServersentries are bridged into the session (plugin skills join the skill-discovery roots — a plugin with noskillssection but a conventionalskills/directory, the Claude marketplace's default layout, contributes it too; plugin MCP servers connect as<plugin-id>.<server>); a plugin's slash commands are bridged too, including the Claudecommands/*.mdprompt commands (each injected as a user turn with$ARGUMENTSsubstituted), registered under their bare name or the namespacedplugin:<id>:<name>trigger and listed in the/menu and/help; pluginagents/*.mdprofiles join agent discovery (YAML frontmatter accepted, project agents win name clashes), and plugin-declaredhooksfire on the matching session lifecycle events (bothpre_tool_useand Claude'sPreToolUsespellings accepted; thehooks.jsonfile and the group{matcher, hooks: [...]}shape are read, a plugin hook getsCLAUDE_PLUGIN_ROOTand the Claude event JSON on stdin, and a blocking Stop hook can feed findings back before the turn ends)./plugins codexand/plugins claudebrowse each store's official marketplace (StoreProvidernormalises the Codex and Claude document shapes); each panel carries a left-hand navigator column split into a category navigator (top) and a marketplace navigator (bottom), each listingALLplus the distinct values the fetched index declares, operated by keyboard (Tab/BackTabcycle focus,Up/Downmove-and-apply,Enterapply,cclear the focused navigator) and mouse (click a row, wheel to scroll); the category navigator additionally carries anInstalledpseudo-category in row 1, directly belowALL, which filters the results to the plugins already in the store scan (matching the plugin id, so an installed plugin that declares no category still shows) and composes with the query and marketplace filters; every navigator row appends the number of plugins under that value asName (N)(theALLrow counts the whole index, derived from the full fetched index so the count is stable as a query or filter narrows the list); the search query, category, and marketplace filters compose so the list shows only entries matching all three; a launch may pre-select a category with--category <name>; each result row shows the plugin id, version, the marketplace it came from (the added marketplace's name, or the store label for the base endpoint), and its description, the description taking every column the marketplace leaves so it runs to the panel's edge and is clipped there (the panel widens up to a 140-column ceiling so the marketplace column has room); a row already installed carries a bold green*in a one-column lane beside the>cursor gutter (every other row paints a blank there, keeping the columns aligned); the result list is sorted alphabetically by plugin id (case-insensitive) and a query or category filter narrows the already-sorted set. A search box sits along the panel's bottom edge with the live filter field on the left and a click-to-clear[x] clearbutton on the right, so the active query can be wiped with one click;/plugins addalso accepts agit+<https-url>#<ref>[:<subpath>]git source; a freshly installed plugin is recorded enabled and loads at the next session start (no JavaScript runs during the install); managed through/plugins list|add|remove|enable|disable|test|stores|marketplace|helpin the TUI (/plugins list [--verbose]opens an interactive table panel with the capability blocks listed at the end;Spacetoggles the highlighted plugin's enabled state) and theragent plugins <sub>CLI (/plugins marketplace showand/plugins marketplace <codex|claude> listlist the marketplaces configured for each store, one section per store with a name/url/description table;/plugins marketplace <codex|claude> add <source>registers an additional marketplace from anowner/reposlug, an SSH remote, anhttps://URL, or a local directory, in the user-globalplugins.stores.marketplaces, and the two browse panels fetch and merge every configured marketplace into the one panel); a loaded index also has each plugin's own version and description resolved from its manifest off the event loop (the vendor listings omit them, Codex especially), with aloading details...title hint and a-version marker while a value stays unknown;plugins.enabled: falsemakes the subsystem inert
- Connector system — a Claude-connector-equivalent catalogue of named
integrations (Google Drive, Slack, GitHub, Git, Postgres, Puppeteer, and the
wider community catalogue) that reach an external system through one or more
MCP servers; a connector is a catalogue entry (display name, category, auth
shape, and one or more servers) on top of the MCP transport ragent already
speaks. Managed through the thirteen-subcommand
/connectorsfamily (list [--verbose] [--category <name>],claude [query] [--category <name>] [--refresh],add <id|source> [--force],remove <id>,enable <id>,disable <id>,connect <id>,disconnect <id>,auth <id>,test <id>,stores [--check],marketplace show|claude list|add|remove,help) in the TUI and theragent connectors <sub>CLI./connectors claudeopens an interactive, off-the-event-loop catalogue browser wearing the same design language as/plugins claude(filter by query, category, and marketplace; browse; install with one key): a calm slate accent frame and a structured title line; a left column split into aCategoriesnavigator above aMarketplacenavigator, each under a reversed-video title band with every row labelledName (N); a fixed dark-on-light column-heading row (Id,Category,Marketplace,Description) pinned above the zebra-banded results; each row shows the connector id, its category, the marketplace it came from (or-for a local install) and its description running to the panel's right edge, with a bold green*in a one-column lane on an installed connector; a centred footer of key hints and a bottomsearch:box with a clickable[x] clearbutton. Every connector list (list,claude,search) is sorted alphabetically by connector id (case-insensitive) and the filters narrow the already-sorted rows; the category navigator listsALL, anInstalledpseudo-category, then the catalogue's distinct categories, operated by keyboard (Tab/BackTabcycle the results and the two navigators,Up/Downmove the focused pane,Enterapplies,cclears) and mouse (click a row in either navigator, wheel to scroll, click[x] clear); the panel merges the base catalogue endpoint and every marketplace added with/connectors marketplace claude add, and resolves each entry's blank description from its own repository manifest off-loop with aloading details...title hint),/connectors test <id>runs an isolated connect-and-invoke harness that never touches the live session, and/connectors stores [--check]reports each catalogue endpoint and its provenance. Connectors install enabled;enableconnects their servers now in a running session.connectors.enabled: falsemakes the subsystem inert
- Automation service — named, schedulable or webhook-triggered agent runs
with durable run history and execution-backend confinement (spec
openhandsFR-013, FR-014, FR-018, FR-033). A public webhook ingress (POST /auto/<id>) enqueues a run with the request body as context; a background scheduler fires schedule-triggered automations (same grammar as/cron); every terminal run is recorded with its automation id, trigger, times, outcome, backend, and output reference, and can notify Slack/GitHub/Linear/Notion/a generic webhook. A run executes only in its configured backend. Managed through/automation [list],/automation runs <id>,/automation run <id>,/automation helpin the TUI,ragent automation list|runs <id>|run <id>on the CLI, andGET /automation,GET /automation/runs/{id},POST /automation/{id}/runover HTTP.automation.enabled: false(or an absent block) makes the subsystem inert - OpenAPI 3.1 contract and typed client — the REST API is described by an
OpenAPI 3.1 document served at
GET /openapi.json, rendered from a single route table in the server crate so it cannot drift from the served routes; a companion test asserts the table and the router agree in both directions. The same table generates a dependency-free typed TypeScript client (docs/openapi/ragent-client.d.ts), emitted from the CLI withragent openapi --client. The document carries no runtime data or secrets, so/openapi.jsonis public while every described operation declares the native bearer security scheme - OpenAI-compatible surface — an inbound
POST /v1/chat/completionsandGET /v1/modelsadapter over the sameSessionProcessoragent loop, behind the native bearer token (FR-003, FR-024).stream:falsereturns an OpenAIchat.completionJSON object;stream:truestreamschat.completion.chunktext/event-streamevents terminated bydata: [DONE](FR-011, FR-012). Enable it withopenai.enabledplus anopenai.token; enabling it without a token makesragent serverefuse to start the surface rather than serve it unauthenticated (FR-032). Permission checks are preserved on both paths (FR-038). - Input queue — the TUI input field stays editable while the primary agent
executes: each
Enterappends the message to a bounded FIFO queue (default 32 entries, configurable viainput_queue_capacity), a two-digit counter appears before the prompt, and the oldest entry runs at each turn boundary; control it with theAlt+Qmenu (Next/Stop/Clear/Show, navigated withUp/Down/Enter) or/queue [list|clear|next|help]; theShowrow opens a scrollable panel of the queued entries whereEntermoves the highlighted entry one step toward the front andDelremoves it - Teams & Swarms — multi-agent coordination with named teammates, shared task lists,
mailbox messaging, and swarm decomposition for parallel work (
/swarm <prompt>)
- Autopilot mode — autonomous operation with configurable iteration limits and
permission auto-approval (
/autopilot on [--max-tokens N] [--max-time N]) - Config error reporting — actionable JSON parse diagnostics showing file path, line, column, problematic source line, and caret marker
- UI internationalisation — opt-in locale message catalog (English fallback
for any missing key) for the status-bar labels, the
/helpheader, and panel footers, configured via thei18nconfig section or the/i18n on|off|status|list|<locale>command; a non-English ambientLANGwith an installed catalog enables it automatically
git clone https://github.com/thawkins/ragent.git
cd ragent
cargo build --release
# Binary is at target/release/ragentRequires Rust 1.85+ (edition 2024; the pinned toolchain is stable).
Incremental compilation is disabled workspace-wide (.cargo/config.toml sets
[build] incremental = false, and [profile.dev] / [profile.test] repeat it)
because the configured sccache wrapper cannot cache incremental artifacts, so
the cache only consumed disk. Expect full rebuilds; BUILDSTATS.md records the
measured cost of each step on the reference machine (release build 7m 37s /
1.80 GiB, debug build 2m 41s / 2.40 GiB, full test run 9m 12s / 14.92 GiB,
coverage run 9m 58s / 15.82 GiB).
Every crate builds one integration-test binary from its tests/ tree
(autotests = false plus a single [[test]] name = "all" that #[path]-includes
each tests/test_*.rs file), so a full cargo test links 19 targets instead of
~950. Run one file by filter:
cargo test -p ragent-tui --test all test_slash_commands::# Configure an API key
export ANTHROPIC_API_KEY="sk-..."
# or
export OPENAI_API_KEY="sk-..."
# or (for Azure AI Foundry)
export AZURE_AI_FOUNDRY_API_KEY="sk-..."
# or (for Generic OpenAI API provider)
export GENERIC_OPENAI_API_KEY="sk-..."
# or (for OpenRouter)
export OPENROUTER_API_KEY="sk-or-..."
# Launch the interactive TUI
ragent
# Run a one-shot prompt
ragent run "Explain this codebase"
# Check that the install is ready (no model or tool is invoked)
ragent run --dry-run "hello"
# Start the HTTP server only
ragent serve --addr 127.0.0.1:9100Use OpenRouter models directly from the CLI:
ragent run --model openrouter/anthropic/claude-sonnet-4 "Refactor this function"Generic OpenAI-compatible endpoint (including custom port) can be configured in
ragent.json:
{
"provider": {
"generic_openai": {
"env": ["GENERIC_OPENAI_API_KEY"],
"api": { "base_url": "http://127.0.0.1:8080" }
}
}
}ragent [OPTIONS] [COMMAND]
Commands:
run Execute agent with prompt
serve Start HTTP server only
orchestrate Run a small orchestration example (demonstrates multi-agent coordinator)
session Manage sessions (list, resume, export-archive, import)
memory Manage persistent memory (export, import, list)
auth Configure provider authentication
models List available models
config Show resolved configuration (show, check)
research Manage research items under `research/`
spec Run spec commands from the CLI (the `/spec` slash-command parity surface)
plugins Manage plugins (the `/plugins` slash-command parity surface)
connectors Manage connectors (the `/connectors` slash-command parity surface)
openapi Emit the OpenAPI 3.1 document (or `--client` for the generated typed client)
automation Manage automations (the `/automation` slash-command parity surface)
acp-server Serve the ACP endpoint on stdio for IDE clients (features acp-server)
new Scaffold a new project in the current directory (the `/new` command)
Options:
--model <MODEL> Override model (provider/model format)
--agent <AGENT> Override agent [default: general]
--log-level <LOG_LEVEL> Log level [default: warn]
--no-tui Disable TUI, use plain stdout
--yes Auto-approve all permissions
--log Show the log panel in the TUI
--config <CONFIG> Path to config file
--maxsteps <MAXSTEPS> Maximum number of agentic loop steps (default: 500)
--dry-run Run a readiness check without invoking any model or tool
--json Emit the dry-run readiness report as JSON
--no-git-context Disable automatic git context injection
--no-readme-context Disable automatic README context injection
-V, --version Print the ragent version and exit
ragent run --dry-run is the fastest way to confirm a machine is set up: it loads
config, resolves the provider, lists the registered skills and tools by category, and
connects MCP servers, then prints a READY / NOT READY verdict.
ragent reads configuration from ragent.json (or ragent.jsonc) in the .ragent/
directory, with fallback to ~/.config/ragent/ragent.json.
A repository's .ragent/ragent.json is untrusted input, so Config::merge_project
strips the privileged keys a project may not set: yolo, permission allow-rules,
bash allow/deny lists, dirs allow/deny lists and allowed roots, telemetry,
hooks, openai, mcp (stdio servers spawn subprocesses with no prompt), acp
(agents spawn verbatim and it controls the editor-facing server), and every
provider's api block (which redirects the credential and prompt stream). These must
live in the user-global config. Rejected keys are logged at warn!.
See the full configuration schema in SPEC.md and the automation manual in docs/howtos/slashcommands/automation.md.
You can define your own agents as JSON files using the Open Agentic Schema Framework (OASF) standard. Place them in:
~/.ragent/agents/— user-global (all projects)~/.config/ragent/agents/— user-global (all projects; XDG config location, takes priority over~/.ragent/agents/).ragent/agents/— project-local (this project, highest priority)
ragent loads them automatically at startup. Use /agents to list loaded agents
and view diagnostics, or /agent to open the interactive picker (custom agents
are marked with a yellow [custom] badge).
See docs/howtos/custom-agents.md for the full schema
reference, template variables ({{WORKING_DIR}}, {{FILE_TREE}}, {{AGENTS_MD}},
{{DATE}}), permission rules, and worked examples — the manual carries a
complete minimal OASF document and a security-reviewer profile you can copy
straight into .ragent/agents/.
Scaffold a brand-new, agent-friendly project in an empty directory with one command:
# TUI
/new --language rust --type cmdline
# CLI
ragent new --language rust --type cmdlineThe command validates the directory is empty, generates the ragent workspace
(.ragent/, specs/, log/, .gitignore, AGENTS.md), a runnable
hello-world artifact set for rust/python/go/typescript in
library/cmdline/tui/gui/webapp layouts, starter documentation (README.md,
QUICKSTART.md, STATS.md, docs/), initialises git with an initial
commit, and — with --github or --gitlab — creates a private hosting
repository, sets it as origin, and pushes.
# Add a framework stack (Rust: axum, warp, raylib, gtk4, ratatui)
ragent new --language rust --type cmdline --stack axum
# Create the project on GitHub or GitLab (mutually exclusive)
ragent new --language python --type library --gitlabSee docs/howtos/newproj.md for the full manual; /new help
prints the registry-derived accepted-value lists.
Teams let one lead session coordinate multiple teammates with shared tasks and mailbox messaging.
Quick flow:
- Create a team:
/team create <name>(orteam_create) - Re-open an existing team:
/team open <name> - Spawn teammates:
team_spawn - Add/list/claim/complete tasks:
team_task_create,team_task_list,team_task_claim,team_task_complete - Communicate:
/team message ...orteam_message, plusteam_read_messages - Reset/close/delete team state:
/team clear,/team close,/team delete <name> - Cleanup when finished:
/team cleanuporteam_cleanup
Docs and examples:
- Guide:
docs/userdocs/TEAMS.md - How-to manual:
docs/howtos/teams.md - Example blueprints:
.ragent/blueprints/teams/(code-review,parallel-feature,debate)
The project is a Cargo workspace built from 18 focused crates:
| Crate | Purpose |
|---|---|
ragent-agent |
Agent/runtime layer: sessions, orchestration, MCP, memory, tool registry |
ragent-bench |
Benchmark runner shared between the TUI and the CLI |
ragent-codeindex |
Indexing: tree-sitter parsing, SQLite store, Tantivy FTS, file watcher |
ragent-config |
Configuration types, defaults, and parsing |
ragent-connectors |
Connector catalogue, store, providers, MCP bridge, /connectors |
ragent-llm |
Provider clients and model registry (14 providers + Model Router) |
ragent-plugins |
Codex/Claude dialect plugins, sandboxed JS runtime, /plugins |
ragent-research |
Web/local research gathering, synthesis, RESEARCH.md output |
ragent-server |
Axum HTTP routes and SSE streaming |
ragent-specs |
Spec lifecycle: discovery, validation, review, archival, JTBD |
ragent-storage |
SQLite storage, snapshots, encrypted credentials |
ragent-surface |
Shared helpers for the plugin/connector command surfaces |
ragent-telemetry |
OpenTelemetry instrumentation and OTLP export |
ragent-tools-core |
Core shell, file and search tools |
ragent-tools-extended |
Extended document, web, memory and codeindex tools |
ragent-tools-vcs |
Git, GitHub and GitLab tool surface |
ragent-tui |
Ratatui terminal interface |
ragent-types |
Shared IDs, events, messages and sanitization primitives |
The binary entry point (src/main.rs) wires these crates together behind a clap CLI.
User Input
│
▼
┌──────────┐ ┌──────────────┐ ┌──────────────┐
│ TUI │◄──►│ Event Bus │◄──►│ HTTP Server │
└────┬─────┘ └──────┬───────┘ └──────┬───────┘
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────────┐
│ Session Processor │
│ (agent loop → LLM call → tool execution) │
└──────────────────┬──────────────────────────┘
│
┌─────────┼─────────┐
▼ ▼ ▼
┌─────────┐ ┌──────┐ ┌────────┐
│Provider │ │Tools │ │Storage │
│(LLM API)│ │ │ │(SQLite)│
└─────────┘ └──────┘ └────────┘
Criterion benchmarks ship with ragent-agent, ragent-bench, ragent-codeindex,
ragent-research, ragent-server, ragent-storage, and ragent-tui. See
docs/userdocs/bench.md for the TUI benchmark runner and
docs/howtos/slashcommands/bench.md for the
/bench command family.
# Run crate benchmarks
cargo bench -p ragent-tui
cargo bench -p ragent-agent
cargo bench -p ragent-codeindexKey optimisations include:
- DashMap replaces
RwLock<HashMap>in the orchestrator, reducing lock contention - LRU file-read cache (256-entry, mtime-keyed) avoids redundant disk I/O
- Rayon parallel glob walk for large directory trees
- Incremental snapshots store only changed files (via
similardiffs) - Async storage writes via
tokio::task::spawn_blockingkeep the executor free - Phased-lock code-index graph build on a dedicated OS thread keeps FTS search available while the semantic graph is derived
v1.0.138 — The core architecture, tool system (148 tools across 21 categories in the default build), TUI, HTTP server, memory system, teams/swarm coordination, spec management, skills system, research system, plugin and connector systems, pluggable execution backends, ACP integration, the automation service, and multi-layered security are functional and under active development.
See CHANGELOG.md for the release-by-release history of every feature, fix, and change.
Related documents:
- SPEC.md — the full specification and requirement history (incl. §21.4 on the one-test-binary-per-crate layout)
- STATS.md — line, file, test and per-crate composition statistics
- BUILDSTATS.md — measured build, test and coverage time/disk cost
- QUICKSTART.md — the guided feature tour
- TUI-QUICKSTART.md — running and driving the terminal UI
- docs/howtos/ — one how-to manual per subsystem
- docs/howtos/tools/INDEX.md — the full tool catalog
- docs/reports/testconsolidation-review.md — the test-binary consolidation review and rollout record
MIT











{ "provider": { "anthropic": { "thinking": { "enabled": true, "level": "low" }, "models": { "claude-sonnet-4-20250514": { "thinking": { "enabled": true, "level": "high", "budget_tokens": 16000 } } } } }, "defaultAgent": "general", "permissions": [ { "permission": "file:write", "pattern": "src/**", "action": "allow" } ], "memory": { "enabled": true, "structured": { "enabled": true }, "semantic": { "enabled": false, "dimensions": 384 } }, "compaction": { "auto": true, "threshold": 0.7, "buffer": 0.10, "keep": { "tokens": 0.20 }, // Optional: route compaction to a fast/cheap model instead of the // session's primary model. Default: session model. // "model": { "provider_id": "ollama", "model_id": "qwen2.5:1.5b" }, // Optional: cap summary output tokens (default 1500) and per-tool-output // truncation in the compaction prompt (default 2000). // "summary_tokens": 1500, // "tool_output_max_chars": 2000 }, "tool_visibility": { "github": true, "gitlab": true, "teams": true, "agents": true, "plan": true, "codeindex": true, "masterfetch": true }, // Execution backend (spec `openhands` FR-001, FR-026). Omitted = `local` // (host execution, FR-019). `backends` declares the registry entries the // `/backend` switcher and the container backend read; `credentials` names // encrypted-store credentials injected as container env vars at spawn time // (the value is never in this file; FR-010). "execution_backend": "podman", "backends": [ { "id": "sandbox", "name": "Podman sandbox", "kind": "podman", "image": "ghcr.io/yourorg/ragent-sandbox:latest", "workspace": "/projects", "credentials": ["EXAMPLE_API_KEY"] } ], // LLM security analyzer (spec `openhands` FR-006, FR-017). Opt-in; a // tightening-only layer over the static permission rules. "security_analyzer": { "enabled": true, "model": { "provider_id": "ollama", "model_id": "qwen2.5:1.5b" } }, // OpenAI-compatible inbound surface (spec `openhands` FR-012, FR-024, // FR-032). When `enabled` is true a `token` (or the ambient `RAGENT_TOKEN`) // is required or `ragent serve` refuses to start the surface. "openai": { "enabled": true, "token": "sk-ragent-local" }, // UI internationalisation (spec `openhands` FR-027). Opt-in; a non-English // ambient `LANG` with an installed catalog enables it automatically. "i18n": { "enabled": true, "locale": "fr" }, // Plugin subsystem (defaults shown). `enabled: false` makes the whole // subsystem inert (no discovery or loading). "plugins": { "enabled": true, "max_execution_ms": 5000, "max_entry_ms": 10000, "max_memory_mb": 64 }, // Connector subsystem (defaults shown). `enabled: false` makes the whole // subsystem inert (no discovery, catalogue fetch, or connection). "connectors": { "enabled": true, "store_dir": null, "stores": { "timeout_ms": 10000, "max_index_bytes": 2097152, "cache_ttl_secs": 3600 }, "credentials": {} }, // Automation service (spec `openhands` FR-013, FR-014, FR-018, FR-033). // An absent block leaves the subsystem inert; `enabled: true` starts the // scheduler and the webhook ingress. "automation": { "enabled": true, "run_history_cap": 500, "scheduler_tick_secs": 30, "automations": [ { "id": "on-issue", "agent": "general", "prompt": "Triage issue {{payload}}", "trigger": { "kind": "webhook" }, "backend": "local", "dispatch": [ { "kind": "slack", "url": "https://hooks.slack.com/...", "token_env": "SLACK_BOT_TOKEN" } ] }, { "id": "nightly", "trigger": { "kind": "schedule", "schedule": "every 2m" } } ] } }