The open-source coding agent you control
Aether has no hardcoded prompts or tools, so you control every token in context. Embrace MCP without bloat, and go from minimal to batteries-included in a few lines of config. Use it in a TUI, IDE, headlessly, or as a Rust/TS library.
$ brew install contextbridge/tap/aether$ curl -fsSL aether-agent.io/install | sh$ cargo install aether-agent-cliUse any LLM you want, cloud or local
You can bring your own too.
Cloud
{ "agents": [ { "name": "Plan", "description": "Plans implementation strategy", "model": "codex:gpt-5.5", "userInvocable": true, "reasoningEffort": "high", "prompts": [".aether/PLAN.md"] }, { "name": "Build", "description": "Builds features and fixes bugs", "model": "zai:glm-5.1", "userInvocable": true, "prompts": [".aether/BUILD.md"] }, { "name": "Fast", "description": "Quick tasks and lookups", "model": "openai:gpt-5.5", "userInvocable": true, "prompts": [".aether/FAST.md"] } ]}Local
{ "agents": [ ... { "name": "Local", "description": "Runs locally via Ollama", "model": "ollama:llama3.2", "userInvocable": true, "prompts": [".aether/LOCAL.md"] } ]}Alloy multiple models together
{ "agents": [ ... { "name": "Alloy", "description": "Mixes cloud and local models", "model": "zai:glm-5.1,ollama:llama3.2", "userInvocable": true, "prompts": [".aether/ALLOY.md"] } ]}Control every token in your system prompt
Start with a blank slate and add only what you need.
Start with a blank slate
$ aether show-prompt -a Build
---
Prompt chars: 0Tool schema chars: 0Est. tokens: ~ 0MCP tools: 0Use any markdown files you want
{ "agents": [ { "name": "Build", "description": "Builds features and fixes bugs", "model": "zai:glm-5.1", "userInvocable": true, "reasoningEffort": "high", "prompts": [".aether/BUILD.md", "AGENTS.md"] } ]}# Build AgentYou are a staff+ level engineer....# AgentsUse the Explorer agent to search code....View your agent's system prompt with a single command
$ aether show-prompt -a Build# System PromptYou are an expert senior Rust engineer....
# Agents
Use the Explorer agent to search code....
---
Prompt chars: 120Tool schema chars: 0Est. tokens: ~ 30MCP tools: 0Connect tools via MCP servers (local or remote)
Be minimal…or maximal. Give your agent a single tool (Bash) and point
it at some CLIs + skill files. Or, go full batteries-included by adding
a few lines to your .aether/mcp.json file.
Batteries included MCPs
coding— file I/O, grep, bash, web, and LSP-backed coding toolsskills— reusable skills, rules, and notessubagents— spawn parallel child agents with their own models and toolstasks— task tracking for multi-step work, with optional persistencesurvey— allow the agent to ask structured questionsplan— submit markdown plans for approval and feedback
{ "agents": [ { "name": "Build", "description": "Builds features and fixes bugs", "model": "zai:glm-5.1", "userInvocable": true, "prompts": [".aether/BUILD.md", "AGENTS.md"], "mcps": [".aether/mcp.json"] } ]}{ "servers": { "coding": { "type": "in-memory", "args": ["--rules-dir", ".aether/skills"] }, "skills": { "type": "in-memory", "args": ["--dir", ".aether/skills", "--notes-dir", ".aether/notes"] }, "subagents": { "type": "in-memory" }, "tasks": { "type": "in-memory" }, "survey": { "type": "in-memory" }, "plan": { "type": "in-memory" } }}Any MCP server
{ "servers": { ... "linear": { "type": "http", "url": "https://mcp.linear.app/mcp" } }}MCP tool proxy stops tools from eating your context
{ "servers": { "chrome-devtools": { "type": "stdio", "command": "npx", "args": ["-y", "chrome-devtools-mcp@latest"], "proxy": true }, "linear": { "type": "http", "url": "https://mcp.linear.app/mcp", "proxy": true } }}Run in a TUI, Editor/IDE or Headless
You’ll be up and running in two commands
Run in a TUI
$ aether✓ Created .aether/settings.json✓ Created .aether/mcp.json✓ Created .aether/BUILD.md✓ Created AGENTS.mdLaunching TUI via aether acp...Run in your editor
$ aether acpRun headlessly
$ aether headless "refactor auth"Use as a Library
Embed Aether directly into your app with the Rust runtime or the TypeScript SDK.
Rust SDK
use aether_core::core::{Prompt, agent};use aether_core::events::{AgentMessage, UserMessage};use llm::{ProviderFactory, providers::AnthropicProvider};
let provider = AnthropicProvider::from_env() .await? .with_model("claude-sonnet-4-5");
let (user_tx, mut agent_rx, handle) = agent(provider) .system_prompt(Prompt::text("You are a concise assistant.")) .spawn() .await?;
user_tx.send(UserMessage::text("Review this diff")).await?;
while let Some(message) = agent_rx.recv().await { match message { AgentMessage::Text { chunk, .. } => print!("{chunk}"), AgentMessage::Done => break, _ => {} }}
handle.await_completion().await;TypeScript SDK
import { AetherSession } from "@aether-agent/sdk";
await using session = await AetherSession.start({ cwd: process.cwd(), agent: "Build",});
for await (const message of session.prompt("Review this diff")) { if (message.type === "session_update") { console.log(message.update); }}Ready to build?
Use the full CLI or pick individual crates — aether-core, llm, mcp-servers, wisp, crucible — to compose your own agent.