Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 26 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
<h1 align="center">Aiython</h1>

<p align="center">
<strong>When Python doesn’t know what to do, Aiython does.</strong>
<strong>Put AI at the exact line where your Python program needs it.</strong>
</p>

<p align="center">
Run ordinary Python with inline AI instructions and AI-assisted recovery.
Keep Python in control of the loop. Use typed, inline AI requests where you need judgment.
</p>

<p align="center">
Expand All @@ -25,28 +25,40 @@
>
</p>

Aiython runs Python normally. When Python cannot parse an inline instruction
or cannot continue through an eligible error, Aiython can hand that part to AI
using the live program state, validate the result, and let Python continue.
Aiython runs ordinary Python. At an inline instruction or eligible runtime
error, it can ask a configured model using live program state, check the
result, and resume execution.

```python
kind: Literal["bug", "billing"] = classify this ticket
```

That is not normal Python syntax. With Aiython, it can become part of a running
Python program.
That is not valid Python syntax on its own. Aiython resolves it at runtime;
Python still controls the loop and uses the checked `Literal` value.

## Quick start

Use Python 3.11 or newer. To inspect the included example **without an API key
or a model call**, clone the repo and run:

```bash
git clone https://github.com/sunmodza/aiython.git
cd aiython
uv run --locked aiython --explain examples/recipes/03_loop.py
```

`--explain` shows the detected AI instructions and recovery checkpoints. It
does not run the script. For an actual model-backed run:

### 1. Install

With `uv`:
For a standalone command with `uv`:

```bash
uv tool install aiython
```

Or with `pip`:
Or in your project's Python environment:

```bash
pip install aiython
Expand All @@ -58,12 +70,17 @@ pip install aiython
aiython setup
```

Choose a tool-calling model. Calls can incur provider charges; review the
[permissions and data exposure](#security) before running unfamiliar scripts.

### 3. Run your Python script with Aiython

```bash
aiython app.py
```

You can inspect your own script first with `aiython --explain app.py`.

Modules work the same way:

```bash
Expand Down
1 change: 0 additions & 1 deletion aiython.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
version = 3
model = "openrouter/openai/gpt-6-luna"
env_file = ".aiython/credentials.env"
api_key_env = "OPENROUTER_API_KEY"

# Optional capability routes:
Expand Down
Binary file added assets/readme/social-preview.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ def test_default_and_capability_routes(self):
self.assertEqual(config.profiles['fast'].routes['reranking'][0]['model'], 'cohere/rerank')
self.assertNotIn('secret', str(describe(config)))

def test_checked_in_config_loads_in_a_clean_checkout(self):
source = Path(__file__).resolve().parents[1] / "aiython.toml"
self.path.write_text(source.read_text(encoding="utf-8"), encoding="utf-8")
selected = resolve(self.root / "examples" / "recipes" / "03_loop.py")
self.assertEqual(selected.path, self.path)
self.assertEqual(selected.profiles["default"].model, "openrouter/openai/gpt-6-luna")

def test_project_scoped_credentials_and_process_override(self):
self.path.write_text('version=3\nmodel="openai/test"\nenv_file=".aiython/credentials.env"\napi_key_env="TEST_AI_KEY"\n')
(self.root / '.aiython').mkdir()
Expand Down
Loading