A lightweight CLI for explicit, reproducible AI coding workflows.
Project description
Aethr
A tiny CLI for running explicit AI coding workflows from YAML.
Core Idea
Coding with LLMs is not one-shot generation. Real development is:
plan -> implement -> review -> iterate
Aethr makes those workflows programmable. A run is just:
task + workflow + explicit context + model routing
Aethr is stateless. The only project file it creates is .aethr.yaml.
Demo
Requirements
- Python 3.12+ (
3.12and3.13are tested; older versions are not supported) gitavailable in your shell- Platform: works on macOS, Linux, and Windows (including WSL) when the
Python and
gitrequirements are met - Optional:
opencodeCLI for implementation steps that edit files
Install
pip install aethr
For local development:
pip install -e ".[dev]"
Quick Start
For a review-only workflow:
aethr init review-existing-diff
aethr run "review my current changes before I commit"
If you omit the task entirely, aethr run opens your editor first, then starts
the workflow:
aethr run
For a multi-step implementation workflow:
aethr init plan-implement-review --force
aethr run "add support for loading .env files"
Commands
Initialize a workflow preset (aethr init)
aethr init plan-implement-review
Creates .aethr.yaml from the named built-in preset.
Run a workflow with an inline task (aethr run "...")
aethr run "add support for loading .env files"
Runs the configured workflow immediately with the provided task.
Open your editor and continue interactively (aethr run)
aethr run
Opens your editor for task entry, then starts the workflow.
Preview prompts without calling models (--show-prompt)
aethr run "review my current changes" --show-prompt
Renders step prompts without making model/API calls.
Check version (aethr version)
aethr version
Prints the installed Aethr version and exits.
How Aethr Works
- Task: the instruction you give Aethr.
- Workflow: the YAML file that defines ordered steps.
- Steps: sequential units of work, run in order.
- Roles: named responsibilities such as
planner,reviewer, orwriter. - Context: explicit repo input declared per step.
- Artifacts: structured implementation output such as changed files and diffs, passed forward in memory to later steps.
- Model routing: each role can point at a different LiteLLM model.
Each step receives the task, prior step outputs, and its declared context. The step result stays in memory, streams to the terminal as it is generated, and is printed in a Rich panel when complete.
Example Workflow Config
workflow: review-existing-diff
roles:
reviewer: Review the provided task context as if it were an existing diff.
models:
reviewer: openai:gpt-4o-mini
steps:
- id: review
role: reviewer
context:
- git_diff
For real code changes, Aethr can hand an implementation step to OpenCode:
- id: implement
role: implementer
backend: opencode
unsafe_permissions: true
- id: review
role: reviewer
history_visibility: none
That keeps the workflow explicit while letting a real coding agent edit the
working tree. Leave unsafe_permissions off if you want OpenCode to keep its
normal permission checks.
Built-In Workflows
plan-implement-review: plan a task, then hand implementation to OpenCode before reviewing the latest implementation artifact channel.review-existing-diff: review the current working tree diff.debug-failing-test: diagnose a failing test, propose a fix, review it.add-tests: plan, draft, and review focused test coverage.docs-sync: update docs from the current diff and README context.custom: a minimal one-step workflow to edit freely.
List presets:
aethr init --list
Initialize another preset:
aethr init docs-sync --force
Examples
The examples/ directory contains small workflow files you can copy from:
examples/review-existing-diff.yamlexamples/add-tests.yamlexamples/docs-sync.yaml
These examples intentionally show different providers across roles so you can see routing in practice, not just the default presets.
OpenCode
The default plan-implement-review workflow uses OpenCode for implementation.
Install the opencode CLI if you want that step to edit the working tree.
The reviewer then sees the latest implementation artifact from the previous implementation step: changed files, diff stat, and raw patch text. When no implementation artifact is available yet, Aethr shows a clear placeholder instead of pretending there is patch data.
Explicit Context
Aethr uses explicit context instead of automatic retrieval. That keeps runs easy to understand: the YAML shows exactly what each step can see.
Supported context sources:
git_diff: runsgit diff --no-ext-diff.latest_diff: the most recent implementation artifact block from prior step results (changed files, diff stat, and patch).file:<path>: reads one UTF-8 file relative to the project root.glob:<pattern>: reads matching UTF-8 files relative to the project root, with a small content cap.
Use git_diff when a step should inspect the whole working tree. Use
latest_diff when a later step should inspect only the most recent
implementation artifact from the workflow itself.
Example:
steps:
- id: review-docs
role: reviewer
context:
- git_diff
- file:README.md
- glob:docs/**/*.md
Missing files, empty diffs, non-git directories, and unreadable files appear as clear placeholder notes in the prompt.
Loops
A step can repeat an earlier contiguous slice of the workflow until a condition is met. This stays explicit in YAML and keeps the workflow sequential.
Example:
steps:
- id: implement
role: implementer
backend: opencode
- id: review
role: reviewer
repeat:
back_to: implement
until_review_pass: true
max_iterations: 3
Use this for bounded review/fix cycles. The controller step should emit
Review status: pass when there are no high or medium findings, and
Review status: revise when another pass is needed.
For loop-heavy workflows, you can also narrow step history visibility:
steps:
- id: implement
role: implementer
backend: opencode
history_visibility: latest
Use latest when the next step only needs the most recent result, summary
when you want a compressed history, and none when the step should only see
its explicit context.
Prompt Previewing
Use --show-prompt to see exactly what Aethr would send to each model:
aethr run "review my current changes before I commit" --show-prompt
Aethr does not call models in prompt preview mode. For later steps, it uses a clear placeholder where real previous step output would appear.
Mock Mode
Aethr works without API keys by returning deterministic mock responses.
Aethr also loads a project-level .env automatically before model calls, so
credentials can live alongside the workflow file without extra flags.
You can start from the included template:
cp .env.example .env
Use the models configured in .aethr.yaml:
AETHR_LIVE=1 aethr run "review my current changes"
Override every configured model with one LiteLLM model:
AETHR_MODEL=openai:gpt-4o-mini aethr run "review my current changes"
Auth
Use aethr auth login to write a provider key into the project .env file.
Aethr loads that file automatically on the next run.
aethr auth login openai
aethr auth status
Supported providers in the helper are:
openaianthropicgoogle/geminiopenrouterxai
Development
Run tests
Tests live in tests/ and use pytest conventions (test_*.py modules and
test_* functions). Add new tests next to the behavior they cover.
Set up a local test environment first:
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
On Windows PowerShell, activate with:
.venv\Scripts\Activate.ps1
Run the full suite:
pytest
Run a specific test module:
pytest tests/test_workflow.py
Run the CLI from source
Use this when iterating on local changes without reinstalling the package. It executes the CLI entrypoint directly from your working tree.
python -m aethr.cli --help
Useful follow-up commands from source:
python -m aethr.cli init --list
python -m aethr.cli run "review my current changes"
Philosophy
Aethr should feel like:
gitpytestrgcargo
It should not feel like:
- an agent framework
- an autonomous coding platform
- an AI operating system
Aethr intentionally avoids persistence, replay systems, caches, plugins, DAGs, async runtimes, vector search, automatic retrieval, memory systems, and agent abstractions.
If a workflow fails, Aethr writes a temporary checkpoint file and prints a
compact resume command. Pass that checkpoint back with --resume-checkpoint
to continue from the next step without rerunning the earlier ones. Use
--verbose if you want the raw checkpoint JSON.
Future Work
One likely future UX is workflow promotion: take a one-off run that worked and
turn it into an editable .aethr.yaml workflow. The idea is to help users go
from ad hoc sessions to repeatable workflows without introducing session
storage, replay systems, or hidden history.
Architecture
aethr/
cli.py
config.py
context.py
executor.py
llm.py
prompts.py
workflow.py
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file aethr-1.0.0.tar.gz.
File metadata
- Download URL: aethr-1.0.0.tar.gz
- Upload date:
- Size: 37.1 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7aece5b932cb2617b168a78dd5a1fe67b88722e35a493f5a8eea2aa8ee2b5aca
|
|
| MD5 |
dd943975b197dd7add0bd17f90d088ff
|
|
| BLAKE2b-256 |
daf7ca69045e3914405a77d8f74dbbe96ab5898489cf956d8d98854defe0f026
|
File details
Details for the file aethr-1.0.0-py3-none-any.whl.
File metadata
- Download URL: aethr-1.0.0-py3-none-any.whl
- Upload date:
- Size: 36.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c2dfdbe8ca50e20ffc8b38674079d2f101d4ea1c123222a5906c220cc6bc25e3
|
|
| MD5 |
a84a34d82062e2f9dee2c3c25fd3e308
|
|
| BLAKE2b-256 |
f072aede11c2f8096e97d0165e69c94f0eb318ae1b1eb95e2c34f946b97456d3
|