Ares is a terminal-first coding agent with a persistent Python workspace. It keeps conversations and execution history on your machine, while using an OpenRouter model for inference.
The model works through repl_py, a persistent IPython tool. It can use Python
for inspection and data work, or a %%bash cell for shell commands. Variables,
imports, and loaded data remain available for the lifetime of the Ares process.
- A fullscreen TypeScript terminal interface with live agent, tool, and subagent status.
- A persistent IPython kernel that starts in the target working directory.
- Process-isolated subagents for independent, focused work.
- Progressive skills that load their full instructions only when needed.
- A durable default harness for prompts, skills, and subagent specifications.
- Strict append-only JSONL conversation files and a SQLite query mirror.
- An optional local React dashboard for live and past
repl_pyexecutions. - A local HTTP API connecting the terminal client to the Python runtime.
- An OpenRouter-backed model client with a configurable local API key.
- Python 3.11 or later
- uv
- An OpenRouter API key
- Node.js 22.19 or later and npm
Clone the repository and install both the Python runtime and terminal client:
uv sync
cd terminal_ui
npm install --ignore-scripts
cd ..Set an OpenRouter key in your shell:
export OPENROUTER_API_KEY="your-key"You can instead place either OPENROUTER_API_KEY or OPEN_ROUTER_API_KEY in a
.env file at the repository root. Keep keys out of version control.
Start Ares from the Ares repository:
uv run aresTo work in another project, run the Ares project explicitly while your shell is in the target workspace:
cd /path/to/project
uv run --project /path/to/ares aresPass an initial task as an argument when useful:
uv run ares "Inspect this project and explain its test setup"Ares uses the current directory as the session and IPython-kernel workspace.
The terminal supports these commands:
| Command | Purpose |
|---|---|
/help or ? |
Show available commands. |
/agents |
Show live delegated subagents. |
/tools |
List the root agent's enabled tools. |
/refine [focus] |
Refine the default harness in the background. |
/refine status |
Show the current refinement job. |
/session |
Show the active JSONL transcript and SQLite database paths. |
/clear |
Clear the visible terminal transcript. |
/exit or /quit |
Save the session and close Ares. |
The fullscreen terminal client is the primary interface. It starts a local Ares
API beside the client, creates one session, and sends every message to the same
runtime. That runtime owns the persistent IPython kernel and JSONL/SQLite
storage. Esc cancels the active turn; Ctrl+C closes the client and session.
To run the client and API separately, start the API first:
uv run ares --apiThen, in another terminal:
cd terminal_ui
npm run ares -- --api http://127.0.0.1:8766The root agent always has repl_py. It executes either ordinary Python code or
an IPython shell cell:
# Python values survive later repl_py calls in the same Ares process.
files = list(Path.cwd().glob("*.py"))%%bash
uv run pytest%%bash must be the first line of the cell. Each Ares runtime owns a private
kernel, which starts only when the tool is first used. Ares provisions its
shared kernel environment under ~/.ares/kernel-venv as needed.
The live kernel state is not restored after Ares exits. Resuming a session restores the saved conversation but starts a fresh IPython kernel when the next Python cell runs.
Each cell is limited to 120 seconds. Ares interrupts a cell that exceeds that limit. Standard output, standard error, final results, errors, display data, and timing are captured. Individual output streams are capped at 65,536 characters.
The root agent can assign a focused task to one live child. That child may delegate to one live grandchild, and delegation stops there. A child has its own process, model history, JSONL session, execution trace, and IPython kernel. It shares the parent project files and the UV-provisioned Python environment, but it does not share Python variables, imports, or conversation history.
An agent allowed to delegate uses five parent-only tools:
| Tool | Purpose |
|---|---|
spawn_subagent |
Start a child for one complete, focused task. |
wait_subagent |
Receive new child events using a cursor. |
wait_subagents |
Wait for several children together using their cursors. |
send_subagent |
Continue an idle child with its existing context and kernel. |
close_subagent |
Stop a child and its kernel while retaining its saved session. |
A root child receives the same control tools and may create one grandchild.
The grandchild receives only repl_py. Each delegating agent may have one
active direct child; after that child closes, another may be created. At most
two subagents are therefore live at once. Because all agents share project
files, delegated writes must not overlap.
Ares discovers user skills from ~/.ares/skills and project skills from
.ares/skills in the workspace. A project skill overrides a user skill with
the same name. Each skill lives in a directory matching its name:
.ares/skills/database-migrations/SKILL.md
The file starts with strict YAML frontmatter containing only name and
description:
---
name: database-migrations
description: >-
Plan and review safe database schema migrations. Use when a task changes
tables, columns, indexes, constraints, or stored data.
---
# Database migrations
Full instructions for Ares go here.At the start of the first session, Ares snapshots resolved skills into the
durable default harness and places only each name, description, and artifact
location in the system prompt. When a request matches the description, or names
the skill as $database-migrations, the model reads the complete persisted copy
through repl_py before acting. Skill entries are limited to 32 KB. Later
sessions reuse the current default harness.
Run /refine manually when the trajectory reveals reusable guidance that should
improve. You can add a short focus after the command, such as /refine make the validation step explicit. The command returns immediately while a single
background agent reviews the trajectory, inspects the current harness, and uses
typed CRUD operations to stage changes. Use /refine status to inspect that job.
When the trajectory exposes a concrete tedious workflow that is likely to recur,
the refiner may package it as a concise skill with its own trigger description
and reusable procedure. It avoids skills for one-off results, generic advice, or
work already covered by the harness.
Ares maintains one typed default harness containing supplemental prompts, skills,
and subagent specifications. Refinement can create, update, or delete entries in
that state. The agent must inspect the harness before editing it, and Ares
validates and commits its staged changes atomically. A successful /refine
replaces the older default, so later sessions start from the refined state. It
never overwrites installed SKILL.md files or source code. Ares activates
completed changes between turns and uses the refreshed state for the root agent
and newly spawned subagents. Refinement is never triggered automatically.
Every run creates a session file under ~/.ares/sessions and mirrors it into
SQLite at ~/.ares/ares.db.
~/.ares/
├── ares.db
├── sessions/
│ ├── <session-id>.jsonl
│ ├── default.harness.json
│ └── default.harness/skills/<skill-name>/SKILL.md
├── skills/
│ └── <skill-name>/SKILL.md
├── kernel-venv/
└── kernel-ipc-*
JSONL is the source of truth for the conversation. SQLite is a queryable companion used by the terminal and dashboard. When a session is resumed, Ares validates the whole JSONL file and repairs its SQLite copy to match it.
Resume a session with:
uv run ares --resume ~/.ares/sessions/<session-id>.jsonlUse a custom directory for newly created JSONL sessions:
uv run ares --session-dir /absolute/path/to/sessionsUse a different SQLite database for a run:
uv run ares --database /absolute/path/to/ares.dbThe ARES_DB environment variable also changes the default SQLite path.
Each JSONL file has one versioned session header followed by ordered message records:
{"type":"session","format":"ares.session","version":1,"session_id":"550e8400-e29b-41d4-a716-446655440000","created_at":"2026-08-09T12:00:00.000Z","cwd":"/absolute/project/path"}
{"type":"message","id":"550e8400-e29b-41d4-a716-446655440001","sequence":1,"timestamp":"2026-08-09T12:00:00.001Z","message":{"role":"system","content":"You are ARES..."}}Ares rejects malformed transcripts rather than silently discarding data. The validator checks the header, message structure, sequence numbers, UUIDs, timestamps, roles, tool-call shapes, duplicate JSON keys, UTF-8 encoding, and the final newline.
The optional dashboard shows repl_py calls as notebook-style cells, including
source code, standard output, errors, final values, duration, and rich IPython
output such as images and HTML tables. It reads persisted execution history from
SQLite and receives live updates through a local server-sent-events stream.
Build the frontend once:
cd src/ares/dashboard/web
npm install
npm run build
cd ../../../..Then start Ares with the dashboard enabled:
uv run ares --dashboardOpen http://127.0.0.1:8765. The dashboard server shares the terminal session's execution trace, so it observes the same live kernel executions.
Choose another local port when required:
uv run ares --dashboard --dashboard-port 9000For dashboard development, leave Ares running on port 8765 and start Vite in a second terminal:
cd src/ares/dashboard/web
npm run devThe dashboard exposes a small local API:
| Endpoint | Purpose |
|---|---|
GET /api/health |
Confirm the dashboard server is available. |
GET /api/executions |
Return the current execution snapshot. |
GET /api/executions/stream |
Stream execution snapshot changes. |
DELETE /api/executions |
Clear completed executions for the active session. |
GET /api/docs |
Open the FastAPI API documentation. |
The built-in OpenRouter client defaults to stealth/ox-alpha
with a temperature of 0.3. Model requests time out after 60 seconds and are
retried once. A root agent turn can make up to 10 tool-calling iterations.
The dashboard binds to 127.0.0.1, not a network interface. The kernel also
uses local IPC files beneath ~/.ares. Treat both the session files and SQLite
database as local project records that may contain source code, command output,
and conversation content.
src/ares/
api/ HTTP routes, session controllers, schemas, and server lifecycle
agent.py model loop and tool-call handling
cli.py command-line startup and interactive commands
config.py model defaults and runtime limits
llm.py OpenRouter client
prompt.py system prompt
runtime.py per-session resource ownership
dashboard/ FastAPI server and React frontend
harness/ durable state and refinement jobs
skills/ installed skill discovery and validation
storage/ SQLite, JSONL sessions, and execution traces
subagents/ child lifecycle, protocol, and parent-only tools
tools/ kernel, repl_py, and the core tool registry
terminal_ui/
src/ primary Ares terminal client
tui/ reusable terminal rendering library
assets/ branding source files
main.py compatibility launcher
Run Python checks from the repository root:
uv lock --check
uvx ruff check src
uv run python -m compileall src/ares main.pyCheck the terminal client from its own directory:
cd terminal_ui
npm run checkBuild the dashboard from its own directory:
cd src/ares/dashboard/web
npm run buildThe terminal helmet logo is adapted from a design by Freepik.