aegis-harness 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- aegis_harness-0.3.0/.gitignore +182 -0
- aegis_harness-0.3.0/CHANGELOG.md +103 -0
- aegis_harness-0.3.0/LICENSE +21 -0
- aegis_harness-0.3.0/PKG-INFO +205 -0
- aegis_harness-0.3.0/README.md +170 -0
- aegis_harness-0.3.0/pyproject.toml +99 -0
- aegis_harness-0.3.0/src/aegis/__init__.py +9 -0
- aegis_harness-0.3.0/src/aegis/cli.py +291 -0
- aegis_harness-0.3.0/src/aegis/config.py +255 -0
- aegis_harness-0.3.0/src/aegis/core/__init__.py +0 -0
- aegis_harness-0.3.0/src/aegis/core/manager.py +120 -0
- aegis_harness-0.3.0/src/aegis/core/session.py +170 -0
- aegis_harness-0.3.0/src/aegis/drivers/__init__.py +22 -0
- aegis_harness-0.3.0/src/aegis/drivers/acp.py +422 -0
- aegis_harness-0.3.0/src/aegis/drivers/base.py +35 -0
- aegis_harness-0.3.0/src/aegis/drivers/claude.py +115 -0
- aegis_harness-0.3.0/src/aegis/drivers/gemini.py +24 -0
- aegis_harness-0.3.0/src/aegis/drivers/opencode.py +12 -0
- aegis_harness-0.3.0/src/aegis/events.py +181 -0
- aegis_harness-0.3.0/src/aegis/init_wizard.py +365 -0
- aegis_harness-0.3.0/src/aegis/mcp/__init__.py +20 -0
- aegis_harness-0.3.0/src/aegis/mcp/bridge.py +38 -0
- aegis_harness-0.3.0/src/aegis/mcp/runtime.py +78 -0
- aegis_harness-0.3.0/src/aegis/mcp/server.py +289 -0
- aegis_harness-0.3.0/src/aegis/py.typed +0 -0
- aegis_harness-0.3.0/src/aegis/queue/__init__.py +25 -0
- aegis_harness-0.3.0/src/aegis/queue/inbox.py +50 -0
- aegis_harness-0.3.0/src/aegis/queue/jsonl.py +39 -0
- aegis_harness-0.3.0/src/aegis/queue/manager.py +277 -0
- aegis_harness-0.3.0/src/aegis/queue/schema.py +85 -0
- aegis_harness-0.3.0/src/aegis/render.py +51 -0
- aegis_harness-0.3.0/src/aegis/telegram/__init__.py +0 -0
- aegis_harness-0.3.0/src/aegis/telegram/bot.py +63 -0
- aegis_harness-0.3.0/src/aegis/telegram/format.py +27 -0
- aegis_harness-0.3.0/src/aegis/telegram/frontend.py +191 -0
- aegis_harness-0.3.0/src/aegis/tui/__init__.py +8 -0
- aegis_harness-0.3.0/src/aegis/tui/app.py +324 -0
- aegis_harness-0.3.0/src/aegis/tui/metrics.py +110 -0
- aegis_harness-0.3.0/src/aegis/tui/names.py +142 -0
- aegis_harness-0.3.0/src/aegis/tui/pane.py +424 -0
- aegis_harness-0.3.0/src/aegis/tui/picker.py +33 -0
- aegis_harness-0.3.0/src/aegis/tui/state.py +25 -0
- aegis_harness-0.3.0/src/aegis/tui/themes.py +106 -0
- aegis_harness-0.3.0/src/aegis/tui/widgets.py +99 -0
- aegis_harness-0.3.0/src/aegis/workflow/__init__.py +10 -0
- aegis_harness-0.3.0/src/aegis/workflow/decorator.py +54 -0
- aegis_harness-0.3.0/src/aegis/workflow/engine.py +202 -0
- aegis_harness-0.3.0/src/aegis/workflow/runner.py +74 -0
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
# Created by https://www.toptal.com/developers/gitignore/api/python
|
|
2
|
+
# Edit at https://www.toptal.com/developers/gitignore?templates=python
|
|
3
|
+
|
|
4
|
+
# Local aegis config — may hold a Telegram token; never commit
|
|
5
|
+
.aegis.py
|
|
6
|
+
|
|
7
|
+
# Runtime state — queue lifecycle logs + per-handle inbox logs (JSONL).
|
|
8
|
+
.aegis/state/
|
|
9
|
+
|
|
10
|
+
### Python ###
|
|
11
|
+
# Byte-compiled / optimized / DLL files
|
|
12
|
+
__pycache__/
|
|
13
|
+
*.py[cod]
|
|
14
|
+
*$py.class
|
|
15
|
+
|
|
16
|
+
# C extensions
|
|
17
|
+
*.so
|
|
18
|
+
|
|
19
|
+
# Distribution / packaging
|
|
20
|
+
.Python
|
|
21
|
+
build/
|
|
22
|
+
develop-eggs/
|
|
23
|
+
dist/
|
|
24
|
+
downloads/
|
|
25
|
+
eggs/
|
|
26
|
+
.eggs/
|
|
27
|
+
lib/
|
|
28
|
+
lib64/
|
|
29
|
+
parts/
|
|
30
|
+
sdist/
|
|
31
|
+
var/
|
|
32
|
+
wheels/
|
|
33
|
+
share/python-wheels/
|
|
34
|
+
*.egg-info/
|
|
35
|
+
.installed.cfg
|
|
36
|
+
*.egg
|
|
37
|
+
MANIFEST
|
|
38
|
+
|
|
39
|
+
# PyInstaller
|
|
40
|
+
# Usually these files are written by a python script from a template
|
|
41
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
42
|
+
*.manifest
|
|
43
|
+
*.spec
|
|
44
|
+
|
|
45
|
+
# Installer logs
|
|
46
|
+
pip-log.txt
|
|
47
|
+
pip-delete-this-directory.txt
|
|
48
|
+
|
|
49
|
+
# Unit test / coverage reports
|
|
50
|
+
htmlcov/
|
|
51
|
+
.tox/
|
|
52
|
+
.nox/
|
|
53
|
+
.coverage
|
|
54
|
+
.coverage.*
|
|
55
|
+
.cache
|
|
56
|
+
nosetests.xml
|
|
57
|
+
coverage.xml
|
|
58
|
+
*.cover
|
|
59
|
+
*.py,cover
|
|
60
|
+
.hypothesis/
|
|
61
|
+
.pytest_cache/
|
|
62
|
+
cover/
|
|
63
|
+
|
|
64
|
+
# Translations
|
|
65
|
+
*.mo
|
|
66
|
+
*.pot
|
|
67
|
+
|
|
68
|
+
# Django stuff:
|
|
69
|
+
*.log
|
|
70
|
+
local_settings.py
|
|
71
|
+
db.sqlite3
|
|
72
|
+
db.sqlite3-journal
|
|
73
|
+
|
|
74
|
+
# Flask stuff:
|
|
75
|
+
instance/
|
|
76
|
+
.webassets-cache
|
|
77
|
+
|
|
78
|
+
# Scrapy stuff:
|
|
79
|
+
.scrapy
|
|
80
|
+
|
|
81
|
+
# Sphinx documentation
|
|
82
|
+
docs/_build/
|
|
83
|
+
|
|
84
|
+
# PyBuilder
|
|
85
|
+
.pybuilder/
|
|
86
|
+
target/
|
|
87
|
+
|
|
88
|
+
# Jupyter Notebook
|
|
89
|
+
.ipynb_checkpoints
|
|
90
|
+
|
|
91
|
+
# IPython
|
|
92
|
+
profile_default/
|
|
93
|
+
ipython_config.py
|
|
94
|
+
|
|
95
|
+
# pyenv
|
|
96
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
97
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
98
|
+
# .python-version
|
|
99
|
+
|
|
100
|
+
# pipenv
|
|
101
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
102
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
103
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
104
|
+
# install all needed dependencies.
|
|
105
|
+
#Pipfile.lock
|
|
106
|
+
|
|
107
|
+
# poetry
|
|
108
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
109
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
110
|
+
# commonly ignored for libraries.
|
|
111
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
112
|
+
#poetry.lock
|
|
113
|
+
|
|
114
|
+
# pdm
|
|
115
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
116
|
+
#pdm.lock
|
|
117
|
+
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
|
118
|
+
# in version control.
|
|
119
|
+
# https://pdm.fming.dev/#use-with-ide
|
|
120
|
+
.pdm.toml
|
|
121
|
+
|
|
122
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
123
|
+
__pypackages__/
|
|
124
|
+
|
|
125
|
+
# Celery stuff
|
|
126
|
+
celerybeat-schedule
|
|
127
|
+
celerybeat.pid
|
|
128
|
+
|
|
129
|
+
# SageMath parsed files
|
|
130
|
+
*.sage.py
|
|
131
|
+
|
|
132
|
+
# Environments
|
|
133
|
+
.env
|
|
134
|
+
.venv
|
|
135
|
+
env/
|
|
136
|
+
venv/
|
|
137
|
+
ENV/
|
|
138
|
+
env.bak/
|
|
139
|
+
venv.bak/
|
|
140
|
+
|
|
141
|
+
# Spyder project settings
|
|
142
|
+
.spyderproject
|
|
143
|
+
.spyproject
|
|
144
|
+
|
|
145
|
+
# Rope project settings
|
|
146
|
+
.ropeproject
|
|
147
|
+
|
|
148
|
+
# mkdocs documentation
|
|
149
|
+
/site
|
|
150
|
+
|
|
151
|
+
# mypy
|
|
152
|
+
.mypy_cache/
|
|
153
|
+
.dmypy.json
|
|
154
|
+
dmypy.json
|
|
155
|
+
|
|
156
|
+
# Pyre type checker
|
|
157
|
+
.pyre/
|
|
158
|
+
|
|
159
|
+
# pytype static type analyzer
|
|
160
|
+
.pytype/
|
|
161
|
+
|
|
162
|
+
# Cython debug symbols
|
|
163
|
+
cython_debug/
|
|
164
|
+
|
|
165
|
+
# PyCharm
|
|
166
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
167
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
168
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
169
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
170
|
+
#.idea/
|
|
171
|
+
|
|
172
|
+
### Python Patch ###
|
|
173
|
+
# Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration
|
|
174
|
+
poetry.toml
|
|
175
|
+
|
|
176
|
+
# ruff
|
|
177
|
+
.ruff_cache/
|
|
178
|
+
|
|
179
|
+
# LSP config files
|
|
180
|
+
pyrightconfig.json
|
|
181
|
+
|
|
182
|
+
# End of https://www.toptal.com/developers/gitignore/api/python
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to Aegis are documented here.
|
|
4
|
+
The format follows Keep a Changelog; this project uses SemVer (0.x).
|
|
5
|
+
|
|
6
|
+
## [Unreleased]
|
|
7
|
+
|
|
8
|
+
## [0.3.0] - 2026-05-21
|
|
9
|
+
|
|
10
|
+
First public PyPI release as `aegis-harness`. Distribution name is
|
|
11
|
+
`aegis-harness`; the importable package is still `aegis`.
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
- **Multi-provider parity via ACP.** Gemini and OpenCode drivers rewritten
|
|
15
|
+
on the official Agent Client Protocol Python SDK
|
|
16
|
+
(`agent-client-protocol >= 0.10`). Multi-turn, streaming, cancellation,
|
|
17
|
+
and per-session MCP injection are now identical across `claude-code`,
|
|
18
|
+
`gemini`, and `opencode`.
|
|
19
|
+
- **Per-provider config classes** (`ClaudeCode`, `GeminiCLI`, `OpenCode`)
|
|
20
|
+
in `aegis.config`. Legacy flat `Agent(harness=..., model=..., ...)`
|
|
21
|
+
shape still works via a back-compat validator.
|
|
22
|
+
- **Task queues + workflows.** `aegis_enqueue` / `aegis_task_status` MCP
|
|
23
|
+
tools, `QueueManager` (FIFO + max-parallel + substrate-deterministic
|
|
24
|
+
dispatch + JSONL replay), `InboxRouter` with universal sender tagging,
|
|
25
|
+
`@workflow` decorator + `WorkflowEngine` runtime, `aegis workflow
|
|
26
|
+
list/run` CLI, `aegis_run_workflow` MCP tool.
|
|
27
|
+
- **Headless mode.** `aegis serve` runs SessionManager + MCP plane without
|
|
28
|
+
a TUI, with an optional Telegram front-end (`/new`, `/close`,
|
|
29
|
+
`/interrupt`, `/<handle> …`, bare-text routing). Configured via
|
|
30
|
+
`telegram_token` / `telegram_chat_id` / `auto_add_to_telegram_prompt`
|
|
31
|
+
in `.aegis.py`. systemd unit template at `scripts/aegis-serve.service`.
|
|
32
|
+
- **`aegis init` wizard.** Rich-powered interactive wizard that detects
|
|
33
|
+
installed agent CLIs, walks through agent + queue setup, and refuses
|
|
34
|
+
to clobber an upstream `.aegis.py` without `--force`.
|
|
35
|
+
- **TUI polish.** Per-block click-to-copy with hover tooltip, inline
|
|
36
|
+
`WorkingIndicator` (spinner + rotating verb + elapsed timer) mounted
|
|
37
|
+
inside the transcript, glued `ToolUse`↔`ToolResult` blocks,
|
|
38
|
+
max-variety alliterating handle generation (no laureate or adjective
|
|
39
|
+
reuse, letter cycling).
|
|
40
|
+
- **OIDC release workflow.** `.github/workflows/release.yml` publishes
|
|
41
|
+
to PyPI on `v*` tag push using PyPI trusted publishing — no token
|
|
42
|
+
stored in the repo.
|
|
43
|
+
- **Expanded docs.** New pages for Drivers, Queues, Workflows, the MCP
|
|
44
|
+
plane, and an auto-generated API reference via mkdocstrings.
|
|
45
|
+
|
|
46
|
+
### Changed
|
|
47
|
+
- Distribution renamed from `aegis` to `aegis-harness` (the name `aegis`
|
|
48
|
+
was already taken on PyPI). Import path is unchanged.
|
|
49
|
+
- README + docs site rewritten for the multi-provider surface; old
|
|
50
|
+
Phase 1/1.5/2 framing replaced with a current-capability summary.
|
|
51
|
+
- Removed `legacy/` (sidelined FastMCP prototype) and `notes/`
|
|
52
|
+
(scratch markdown). Git history preserves both.
|
|
53
|
+
|
|
54
|
+
### Fixed
|
|
55
|
+
- ACP driver: workaround for an upstream SDK race in `Connection.__init__`
|
|
56
|
+
that was killing every Gemini/OpenCode session on startup.
|
|
57
|
+
- ACP driver: measure `duration_ms` locally in `send()` (the final
|
|
58
|
+
status line was always showing 0.0s).
|
|
59
|
+
|
|
60
|
+
## [0.2.0] - 2026-05-18
|
|
61
|
+
|
|
62
|
+
### Added
|
|
63
|
+
- MCP plane (slice 1): a shared FastMCP HTTP server owned by aegis;
|
|
64
|
+
spawned agents are injected strict + primed and get an `aegis_meta`
|
|
65
|
+
orientation tool.
|
|
66
|
+
- MCP plane (slice 2): `aegis_list_sessions` / `aegis_list_agents` /
|
|
67
|
+
`aegis_handoff` (fire-and-forget inter-agent context transfer);
|
|
68
|
+
per-pane self-reported handle baked into the priming so each agent
|
|
69
|
+
knows who it is and passes that as `from_handle`.
|
|
70
|
+
|
|
71
|
+
### Fixed
|
|
72
|
+
- Driver: large `tool_result` payloads (e.g. reading a SOUL.md-sized
|
|
73
|
+
file) no longer silent-hang a turn. `create_subprocess_exec` now
|
|
74
|
+
uses a 16 MiB `StreamReader` buffer (root cause: 64 KiB default was
|
|
75
|
+
too small for legitimate lines), and `_pump_stdout` has a
|
|
76
|
+
`try/finally` so the stream-closed sentinel always fires. Tool-result
|
|
77
|
+
display is capped at 100 chars. Regression tests cover both
|
|
78
|
+
guarantees.
|
|
79
|
+
|
|
80
|
+
## [0.1.0] - 2026-05-18
|
|
81
|
+
|
|
82
|
+
First tagged release — a usable, personal-infrastructure-grade meta-harness.
|
|
83
|
+
|
|
84
|
+
### Added
|
|
85
|
+
- CLI driver: runs Claude Code via `claude -p` stream-json (bidirectional,
|
|
86
|
+
no log scraping); agent profiles from a Python `.aegis.py`.
|
|
87
|
+
- Full-screen Textual TUI replacing the line REPL.
|
|
88
|
+
- Multi-tab: N independent agent sessions, a sideways-scrolling tab bar,
|
|
89
|
+
per-tab agent profiles, an `AgentPicker` modal, generated handles
|
|
90
|
+
(`adjective-laureate`), cross-tab signalling (state dot + sticky `*` +
|
|
91
|
+
bell).
|
|
92
|
+
- Theme engine (Textual-native) with the default **Ink** theme; themes are
|
|
93
|
+
drop-in.
|
|
94
|
+
- Live status-line metrics: true input (incl. cache) with cached %, output,
|
|
95
|
+
tool calls, turn / session time; provisional while streaming, exact at
|
|
96
|
+
turn end.
|
|
97
|
+
- Lazy session start (harness spawns on first message, not tab open).
|
|
98
|
+
- `aegis --version`.
|
|
99
|
+
|
|
100
|
+
### Notes
|
|
101
|
+
- Not general-public-ready; runs from source via `uv`, drives a local
|
|
102
|
+
`claude` CLI. The earlier FastMCP workflow-engine prototype is preserved
|
|
103
|
+
under `legacy/`, unbuilt.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Alejandro Piad Morffis
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: aegis-harness
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: A multi-agent meta-harness for coding agents — drives Claude Code, Gemini CLI, and OpenCode in one calm full-screen TUI.
|
|
5
|
+
Project-URL: Homepage, https://apiad.github.io/aegis/
|
|
6
|
+
Project-URL: Documentation, https://apiad.github.io/aegis/
|
|
7
|
+
Project-URL: Repository, https://github.com/apiad/aegis
|
|
8
|
+
Project-URL: Issues, https://github.com/apiad/aegis/issues
|
|
9
|
+
Project-URL: Changelog, https://github.com/apiad/aegis/blob/main/CHANGELOG.md
|
|
10
|
+
Author-email: Alejandro Piad <apiad@apiad.net>
|
|
11
|
+
License: MIT
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Keywords: acp,agents,ai,claude,gemini,harness,mcp,opencode,textual,tui
|
|
14
|
+
Classifier: Development Status :: 4 - Beta
|
|
15
|
+
Classifier: Environment :: Console
|
|
16
|
+
Classifier: Environment :: Console :: Curses
|
|
17
|
+
Classifier: Intended Audience :: Developers
|
|
18
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
19
|
+
Classifier: Operating System :: MacOS
|
|
20
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
21
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
+
Classifier: Topic :: Software Development
|
|
24
|
+
Classifier: Topic :: Terminals
|
|
25
|
+
Classifier: Topic :: Utilities
|
|
26
|
+
Requires-Python: >=3.13
|
|
27
|
+
Requires-Dist: agent-client-protocol>=0.10
|
|
28
|
+
Requires-Dist: fastmcp>=3.2.0
|
|
29
|
+
Requires-Dist: httpx>=0.28
|
|
30
|
+
Requires-Dist: pydantic>=2.12.5
|
|
31
|
+
Requires-Dist: rich>=14.3.3
|
|
32
|
+
Requires-Dist: textual>=8.2.6
|
|
33
|
+
Requires-Dist: typer>=0.24.1
|
|
34
|
+
Description-Content-Type: text/markdown
|
|
35
|
+
|
|
36
|
+
# Aegis
|
|
37
|
+
|
|
38
|
+
> A multi-agent meta-harness for coding agents — drives Claude Code,
|
|
39
|
+
> Gemini CLI, and OpenCode side by side in one calm full-screen TUI.
|
|
40
|
+
|
|
41
|
+
[](https://github.com/apiad/aegis/actions/workflows/ci.yml)
|
|
42
|
+
[](https://apiad.github.io/aegis/)
|
|
43
|
+
[](https://pypi.org/project/aegis-harness/)
|
|
44
|
+
[](https://www.python.org/)
|
|
45
|
+
[](LICENSE)
|
|
46
|
+
|
|
47
|
+
Aegis sits **above** the harness. It drives existing coding-agent CLIs —
|
|
48
|
+
`claude` (Anthropic), `gemini` (Google), `opencode` (open-source) — over
|
|
49
|
+
their structured protocols (stream-json and ACP), parses the event
|
|
50
|
+
streams, and re-renders them in a calm Textual TUI where many agents run
|
|
51
|
+
side by side. It adds a routing + delegation plane on top: queues,
|
|
52
|
+
workflows, an MCP server every spawned agent talks to, and an optional
|
|
53
|
+
Telegram front-end.
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
┌ aegis ───────────────────────────────────────────────┐
|
|
57
|
+
│ ● 1 lucid-knuth ·opus· ● 2 wry-hopper ·gemini· * │
|
|
58
|
+
│ │
|
|
59
|
+
│ › explain the retry logic │
|
|
60
|
+
│ │
|
|
61
|
+
│ ⠹ Thinking… (3.2s) │
|
|
62
|
+
│ ⏺ Read(worker.py) │
|
|
63
|
+
│ └ ok │
|
|
64
|
+
│ The retry path lives in _run_turn … │
|
|
65
|
+
│ │
|
|
66
|
+
│ lucid-knuth ·opus· opus·full ↑128k (94% cached) ↓1k │
|
|
67
|
+
│ ───────────────────────────────────────────────────── │
|
|
68
|
+
│ › ask something… │
|
|
69
|
+
└───────────────────────────────────────────────────────┘
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Install
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
pip install aegis-harness # or: uv pip install aegis-harness
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Requires Python 3.13+ and at least one of: `claude`, `gemini`, or
|
|
79
|
+
`opencode` on your `PATH`, signed-in.
|
|
80
|
+
|
|
81
|
+
## Quickstart
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
aegis init # interactive wizard — detects installed CLIs, writes .aegis.py
|
|
85
|
+
aegis # full-screen TUI
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
The wizard finds whichever agent CLIs you have installed and walks you
|
|
89
|
+
through picking a model, permission mode, and optional queues. The
|
|
90
|
+
generated `.aegis.py` is plain Python — edit it freely afterwards.
|
|
91
|
+
|
|
92
|
+
## What you get
|
|
93
|
+
|
|
94
|
+
- **Multi-provider parity** — Claude Code, Gemini, and OpenCode all
|
|
95
|
+
speak through aegis with the same UX (multi-turn, streaming,
|
|
96
|
+
cancellation, per-session MCP injection). Gemini and OpenCode use
|
|
97
|
+
[ACP](https://github.com/zed-industries/agent-client-protocol);
|
|
98
|
+
Claude uses its stream-json bidirectional protocol.
|
|
99
|
+
- **Multi-tab TUI** — N independent agent sessions in one terminal.
|
|
100
|
+
Per-tab profiles, generated alliterating handles
|
|
101
|
+
(`lucid-knuth`, `wry-hopper`), per-block copy-to-clipboard, an inline
|
|
102
|
+
spinner + rotating verb + timer while an agent works, cross-tab
|
|
103
|
+
signalling (state dot + sticky `*` + bell when a backgrounded agent
|
|
104
|
+
finishes).
|
|
105
|
+
- **Honest metrics** — true input (incl. cache) with cached %, output,
|
|
106
|
+
tool calls, per-turn and per-session timing. Provisional while
|
|
107
|
+
streaming, exact at turn end.
|
|
108
|
+
- **Queues + workflows** — first-class inter-agent delegation. Configure
|
|
109
|
+
queues in `.aegis.py`; any agent can call `aegis_enqueue(queue,
|
|
110
|
+
payload)` and get an automatic inbox callback when the worker
|
|
111
|
+
finishes. Write Python workflows that orchestrate multiple agents
|
|
112
|
+
(delegate / send / drain / spawn / close / bash) and run them via
|
|
113
|
+
`aegis workflow run`.
|
|
114
|
+
- **MCP plane** — every spawned agent gets injected with an aegis MCP
|
|
115
|
+
server that exposes orientation (`aegis_meta`), session listing
|
|
116
|
+
(`aegis_list_sessions`, `aegis_list_agents`), peer handoff
|
|
117
|
+
(`aegis_handoff`), and queue dispatch (`aegis_enqueue`,
|
|
118
|
+
`aegis_task_status`). No log scraping anywhere in the stack.
|
|
119
|
+
- **Headless + Telegram** — `aegis serve` runs the SessionManager and
|
|
120
|
+
MCP plane without a TUI, with an optional Telegram front-end so you
|
|
121
|
+
can drive agents from your phone.
|
|
122
|
+
|
|
123
|
+
## Keys
|
|
124
|
+
|
|
125
|
+
| Key | Action |
|
|
126
|
+
|---|---|
|
|
127
|
+
| `Enter` | Send |
|
|
128
|
+
| `Ctrl+T` / `Ctrl+N` | New tab (default agent) / new tab (pick agent) |
|
|
129
|
+
| `Ctrl+W` | Close tab (last → quit) |
|
|
130
|
+
| `Ctrl+1`..`9` / `Ctrl+Tab` / `Ctrl+←→` | Switch tabs |
|
|
131
|
+
| `Escape` | Interrupt the active turn |
|
|
132
|
+
| `Click on a block` | Copy that message / tool result to clipboard |
|
|
133
|
+
| `Ctrl+Q` | Quit |
|
|
134
|
+
|
|
135
|
+
A backgrounded tab that finishes shows a `*` and rings the bell.
|
|
136
|
+
|
|
137
|
+
## Configuration
|
|
138
|
+
|
|
139
|
+
`.aegis.py` is plain Python. The wizard writes one for you; here's the
|
|
140
|
+
shape:
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
from aegis import Agent, ClaudeCode, GeminiCLI, OpenCode
|
|
144
|
+
|
|
145
|
+
agents = {
|
|
146
|
+
"default": Agent(provider=ClaudeCode(model="opus", effort="high",
|
|
147
|
+
permission="auto")),
|
|
148
|
+
"fast": Agent(provider=GeminiCLI(model="gemini-3-flash-preview",
|
|
149
|
+
permission="full")),
|
|
150
|
+
"oss": Agent(provider=OpenCode(model="opencode/kimi-k2.6",
|
|
151
|
+
permission="full")),
|
|
152
|
+
}
|
|
153
|
+
default_agent = "default"
|
|
154
|
+
|
|
155
|
+
queues = {
|
|
156
|
+
"review": {"agent": "fast", "max_parallel": 2},
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Full reference: [Configuration](https://apiad.github.io/aegis/configuration/).
|
|
161
|
+
|
|
162
|
+
## Headless + Telegram
|
|
163
|
+
|
|
164
|
+
`aegis serve` runs the SessionManager and MCP plane without the TUI; add
|
|
165
|
+
a Telegram token to drive it from your phone:
|
|
166
|
+
|
|
167
|
+
```python
|
|
168
|
+
# .aegis.py
|
|
169
|
+
telegram_token = "…" # or set AEGIS_TELEGRAM_TOKEN
|
|
170
|
+
telegram_chat_id = 123456 # the single allowed chat
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Routing inside the chat:
|
|
174
|
+
|
|
175
|
+
- `/new [agent]` — spawn a new session
|
|
176
|
+
- `/close [handle]` — close a session
|
|
177
|
+
- `/interrupt` — interrupt the active turn
|
|
178
|
+
- `/<handle> text…` — one-shot to a specific session
|
|
179
|
+
- bare text — sent to the active session
|
|
180
|
+
|
|
181
|
+
A systemd unit template lives at `scripts/aegis-serve.service`.
|
|
182
|
+
|
|
183
|
+
## Docs
|
|
184
|
+
|
|
185
|
+
Full documentation: **[https://apiad.github.io/aegis/](https://apiad.github.io/aegis/)**
|
|
186
|
+
|
|
187
|
+
- [Install](https://apiad.github.io/aegis/install/)
|
|
188
|
+
- [Usage](https://apiad.github.io/aegis/usage/)
|
|
189
|
+
- [Configuration](https://apiad.github.io/aegis/configuration/)
|
|
190
|
+
- [Drivers](https://apiad.github.io/aegis/drivers/) — Claude / Gemini / OpenCode
|
|
191
|
+
- [Queues](https://apiad.github.io/aegis/queues/) — inter-agent delegation
|
|
192
|
+
- [Workflows](https://apiad.github.io/aegis/workflows/) — Python orchestration
|
|
193
|
+
- [MCP plane](https://apiad.github.io/aegis/mcp/) — the tool surface
|
|
194
|
+
- [Architecture](https://apiad.github.io/aegis/architecture/)
|
|
195
|
+
- [API reference](https://apiad.github.io/aegis/api/)
|
|
196
|
+
|
|
197
|
+
## Status
|
|
198
|
+
|
|
199
|
+
Beta. Personal-infrastructure-grade, evolves fast. Expect change before
|
|
200
|
+
1.0. See the [roadmap](https://apiad.github.io/aegis/roadmap/) for
|
|
201
|
+
what's next.
|
|
202
|
+
|
|
203
|
+
## License
|
|
204
|
+
|
|
205
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# Aegis
|
|
2
|
+
|
|
3
|
+
> A multi-agent meta-harness for coding agents — drives Claude Code,
|
|
4
|
+
> Gemini CLI, and OpenCode side by side in one calm full-screen TUI.
|
|
5
|
+
|
|
6
|
+
[](https://github.com/apiad/aegis/actions/workflows/ci.yml)
|
|
7
|
+
[](https://apiad.github.io/aegis/)
|
|
8
|
+
[](https://pypi.org/project/aegis-harness/)
|
|
9
|
+
[](https://www.python.org/)
|
|
10
|
+
[](LICENSE)
|
|
11
|
+
|
|
12
|
+
Aegis sits **above** the harness. It drives existing coding-agent CLIs —
|
|
13
|
+
`claude` (Anthropic), `gemini` (Google), `opencode` (open-source) — over
|
|
14
|
+
their structured protocols (stream-json and ACP), parses the event
|
|
15
|
+
streams, and re-renders them in a calm Textual TUI where many agents run
|
|
16
|
+
side by side. It adds a routing + delegation plane on top: queues,
|
|
17
|
+
workflows, an MCP server every spawned agent talks to, and an optional
|
|
18
|
+
Telegram front-end.
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
┌ aegis ───────────────────────────────────────────────┐
|
|
22
|
+
│ ● 1 lucid-knuth ·opus· ● 2 wry-hopper ·gemini· * │
|
|
23
|
+
│ │
|
|
24
|
+
│ › explain the retry logic │
|
|
25
|
+
│ │
|
|
26
|
+
│ ⠹ Thinking… (3.2s) │
|
|
27
|
+
│ ⏺ Read(worker.py) │
|
|
28
|
+
│ └ ok │
|
|
29
|
+
│ The retry path lives in _run_turn … │
|
|
30
|
+
│ │
|
|
31
|
+
│ lucid-knuth ·opus· opus·full ↑128k (94% cached) ↓1k │
|
|
32
|
+
│ ───────────────────────────────────────────────────── │
|
|
33
|
+
│ › ask something… │
|
|
34
|
+
└───────────────────────────────────────────────────────┘
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Install
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pip install aegis-harness # or: uv pip install aegis-harness
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Requires Python 3.13+ and at least one of: `claude`, `gemini`, or
|
|
44
|
+
`opencode` on your `PATH`, signed-in.
|
|
45
|
+
|
|
46
|
+
## Quickstart
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
aegis init # interactive wizard — detects installed CLIs, writes .aegis.py
|
|
50
|
+
aegis # full-screen TUI
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
The wizard finds whichever agent CLIs you have installed and walks you
|
|
54
|
+
through picking a model, permission mode, and optional queues. The
|
|
55
|
+
generated `.aegis.py` is plain Python — edit it freely afterwards.
|
|
56
|
+
|
|
57
|
+
## What you get
|
|
58
|
+
|
|
59
|
+
- **Multi-provider parity** — Claude Code, Gemini, and OpenCode all
|
|
60
|
+
speak through aegis with the same UX (multi-turn, streaming,
|
|
61
|
+
cancellation, per-session MCP injection). Gemini and OpenCode use
|
|
62
|
+
[ACP](https://github.com/zed-industries/agent-client-protocol);
|
|
63
|
+
Claude uses its stream-json bidirectional protocol.
|
|
64
|
+
- **Multi-tab TUI** — N independent agent sessions in one terminal.
|
|
65
|
+
Per-tab profiles, generated alliterating handles
|
|
66
|
+
(`lucid-knuth`, `wry-hopper`), per-block copy-to-clipboard, an inline
|
|
67
|
+
spinner + rotating verb + timer while an agent works, cross-tab
|
|
68
|
+
signalling (state dot + sticky `*` + bell when a backgrounded agent
|
|
69
|
+
finishes).
|
|
70
|
+
- **Honest metrics** — true input (incl. cache) with cached %, output,
|
|
71
|
+
tool calls, per-turn and per-session timing. Provisional while
|
|
72
|
+
streaming, exact at turn end.
|
|
73
|
+
- **Queues + workflows** — first-class inter-agent delegation. Configure
|
|
74
|
+
queues in `.aegis.py`; any agent can call `aegis_enqueue(queue,
|
|
75
|
+
payload)` and get an automatic inbox callback when the worker
|
|
76
|
+
finishes. Write Python workflows that orchestrate multiple agents
|
|
77
|
+
(delegate / send / drain / spawn / close / bash) and run them via
|
|
78
|
+
`aegis workflow run`.
|
|
79
|
+
- **MCP plane** — every spawned agent gets injected with an aegis MCP
|
|
80
|
+
server that exposes orientation (`aegis_meta`), session listing
|
|
81
|
+
(`aegis_list_sessions`, `aegis_list_agents`), peer handoff
|
|
82
|
+
(`aegis_handoff`), and queue dispatch (`aegis_enqueue`,
|
|
83
|
+
`aegis_task_status`). No log scraping anywhere in the stack.
|
|
84
|
+
- **Headless + Telegram** — `aegis serve` runs the SessionManager and
|
|
85
|
+
MCP plane without a TUI, with an optional Telegram front-end so you
|
|
86
|
+
can drive agents from your phone.
|
|
87
|
+
|
|
88
|
+
## Keys
|
|
89
|
+
|
|
90
|
+
| Key | Action |
|
|
91
|
+
|---|---|
|
|
92
|
+
| `Enter` | Send |
|
|
93
|
+
| `Ctrl+T` / `Ctrl+N` | New tab (default agent) / new tab (pick agent) |
|
|
94
|
+
| `Ctrl+W` | Close tab (last → quit) |
|
|
95
|
+
| `Ctrl+1`..`9` / `Ctrl+Tab` / `Ctrl+←→` | Switch tabs |
|
|
96
|
+
| `Escape` | Interrupt the active turn |
|
|
97
|
+
| `Click on a block` | Copy that message / tool result to clipboard |
|
|
98
|
+
| `Ctrl+Q` | Quit |
|
|
99
|
+
|
|
100
|
+
A backgrounded tab that finishes shows a `*` and rings the bell.
|
|
101
|
+
|
|
102
|
+
## Configuration
|
|
103
|
+
|
|
104
|
+
`.aegis.py` is plain Python. The wizard writes one for you; here's the
|
|
105
|
+
shape:
|
|
106
|
+
|
|
107
|
+
```python
|
|
108
|
+
from aegis import Agent, ClaudeCode, GeminiCLI, OpenCode
|
|
109
|
+
|
|
110
|
+
agents = {
|
|
111
|
+
"default": Agent(provider=ClaudeCode(model="opus", effort="high",
|
|
112
|
+
permission="auto")),
|
|
113
|
+
"fast": Agent(provider=GeminiCLI(model="gemini-3-flash-preview",
|
|
114
|
+
permission="full")),
|
|
115
|
+
"oss": Agent(provider=OpenCode(model="opencode/kimi-k2.6",
|
|
116
|
+
permission="full")),
|
|
117
|
+
}
|
|
118
|
+
default_agent = "default"
|
|
119
|
+
|
|
120
|
+
queues = {
|
|
121
|
+
"review": {"agent": "fast", "max_parallel": 2},
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Full reference: [Configuration](https://apiad.github.io/aegis/configuration/).
|
|
126
|
+
|
|
127
|
+
## Headless + Telegram
|
|
128
|
+
|
|
129
|
+
`aegis serve` runs the SessionManager and MCP plane without the TUI; add
|
|
130
|
+
a Telegram token to drive it from your phone:
|
|
131
|
+
|
|
132
|
+
```python
|
|
133
|
+
# .aegis.py
|
|
134
|
+
telegram_token = "…" # or set AEGIS_TELEGRAM_TOKEN
|
|
135
|
+
telegram_chat_id = 123456 # the single allowed chat
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Routing inside the chat:
|
|
139
|
+
|
|
140
|
+
- `/new [agent]` — spawn a new session
|
|
141
|
+
- `/close [handle]` — close a session
|
|
142
|
+
- `/interrupt` — interrupt the active turn
|
|
143
|
+
- `/<handle> text…` — one-shot to a specific session
|
|
144
|
+
- bare text — sent to the active session
|
|
145
|
+
|
|
146
|
+
A systemd unit template lives at `scripts/aegis-serve.service`.
|
|
147
|
+
|
|
148
|
+
## Docs
|
|
149
|
+
|
|
150
|
+
Full documentation: **[https://apiad.github.io/aegis/](https://apiad.github.io/aegis/)**
|
|
151
|
+
|
|
152
|
+
- [Install](https://apiad.github.io/aegis/install/)
|
|
153
|
+
- [Usage](https://apiad.github.io/aegis/usage/)
|
|
154
|
+
- [Configuration](https://apiad.github.io/aegis/configuration/)
|
|
155
|
+
- [Drivers](https://apiad.github.io/aegis/drivers/) — Claude / Gemini / OpenCode
|
|
156
|
+
- [Queues](https://apiad.github.io/aegis/queues/) — inter-agent delegation
|
|
157
|
+
- [Workflows](https://apiad.github.io/aegis/workflows/) — Python orchestration
|
|
158
|
+
- [MCP plane](https://apiad.github.io/aegis/mcp/) — the tool surface
|
|
159
|
+
- [Architecture](https://apiad.github.io/aegis/architecture/)
|
|
160
|
+
- [API reference](https://apiad.github.io/aegis/api/)
|
|
161
|
+
|
|
162
|
+
## Status
|
|
163
|
+
|
|
164
|
+
Beta. Personal-infrastructure-grade, evolves fast. Expect change before
|
|
165
|
+
1.0. See the [roadmap](https://apiad.github.io/aegis/roadmap/) for
|
|
166
|
+
what's next.
|
|
167
|
+
|
|
168
|
+
## License
|
|
169
|
+
|
|
170
|
+
MIT — see [LICENSE](LICENSE).
|